'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Licensed Materials - Property of IBM * IBM Cognos Products: Dashboard * (C) Copyright IBM Corp. 2017, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['underscore', '../../../lib/@waca/dashboard-common/dist/core/UniqueHashIdBuilder', '../../../features/content/dataQueryExecution/DataQueryUtils'], function (_, UniqueHashIdBuilder, DataQueryUtils) { var QUERY_RESULTS_SIZE_LIMIT = 1000; // Filter operators constant var OR = 'or'; var IN = 'in'; var GT = 'gt'; var LT = 'lt'; var BETWEEN = 'between'; var NOTBETWEEN = 'notbetween'; var CONTAINSIGNORECASE = 'containsignorecase'; var ISNULL = 'isnull'; // Filter aggregation type var PRE = 'pre'; /** * The singleton class to build the common queryspec shared by visualizations, filters, prompts or other components. */ var CommonQueryBuilder = function () { function CommonQueryBuilder() { _classCallCheck(this, CommonQueryBuilder); } /** * Build single item query spec. * @param {Object} queryDefinition.column - optional: the column used to build the item query. column is mandatory if dataItems is not provided. * @param {Object} queryDefinition.dataItems - optional: if the queryDefinition doesn't have column it must provide dataItems. * @param {Object} queryDefinition.filters - optional: The caller can provide an optional set of filters in querySpec form (as generated by filterEntry.toQuerySpec()) * @param {String} queryContext.searchTerm - optional: the search string used to refine the query result. */ CommonQueryBuilder.buildSingleItemQuery = function buildSingleItemQuery(queryDefinition, queryContext, logger) { var oQuerySpec = {}; var aDataItems = CommonQueryBuilder._buildDataItems(queryDefinition, logger, queryContext); var aProjections = CommonQueryBuilder.buildProjections(queryDefinition, logger); if (!aDataItems.length || !aProjections.length) { logger.warn('Could not build singleItemQuery', this); return oQuerySpec; } oQuerySpec.version = '1'; oQuerySpec.dataItems = aDataItems; oQuerySpec.projections = aProjections; oQuerySpec.limit = queryDefinition.limit || CommonQueryBuilder.getQueryResultsSizeLimit(); if (queryDefinition.queryHints) { oQuerySpec.queryHints = queryDefinition.queryHints; } if (queryDefinition.parameterValues) { oQuerySpec.parameterValues = queryDefinition.parameterValues; } //Allow the caller to optionally pass in filters in the query Definition. var filters = queryDefinition.filters || []; if (!queryContext) { oQuerySpec.filters = filters; return oQuerySpec; } if (queryContext.pageContext) { filters = filters.concat(CommonQueryBuilder.buildFilterFromPageContext(queryContext.pageContext)); } if (queryContext.searchTerm) { filters = filters.concat(CommonQueryBuilder._buildFilterFromSearchTerm(queryDefinition, queryContext.searchTerm)); } if (queryContext.filter) { filters.push(queryContext.filter); } oQuerySpec.filters = filters; return oQuerySpec; }; /** * Build minmax query spec from a column. * @param {Object} queryDefinition.column - mandatory: the column to get the minmax values. * @example of querySpec returned by this function: * { * 'version': '1', * 'dataItems': [ * { * 'id': 'Sheet1.Revenue_Min', * 'itemId': 'Sheet1.Revenue', * 'aggregate': 'min' * }, * { * 'id': 'Sheet1.Revenue_Max', * 'itemId': 'Sheet1.Revenue', * 'aggregate': 'max' * } * ], * 'projections': [ * 'Sheet1.Revenue_Min', * 'Sheet1.Revenue_Max' * ], * 'limit': 1000 * } * */ CommonQueryBuilder.buildMinMaxQueryFromColumns = function buildMinMaxQueryFromColumns(queryDefinition, queryContext, logger) { var oQuerySpec = {}; var maxDataItemId = queryDefinition.column.columnId + '_Max'; var minDataItemId = queryDefinition.column.columnId + '_Min'; var maxDataItem = CommonQueryBuilder._buildDataItems({ 'column': { 'id': maxDataItemId, 'columnId': queryDefinition.column.columnId, 'getAggregation': function getAggregation() { return 'max'; } } }, logger); var minDataItem = CommonQueryBuilder._buildDataItems({ 'column': { 'id': minDataItemId, 'columnId': queryDefinition.column.columnId, 'getAggregation': function getAggregation() { return 'min'; } } }, logger); var aDataItems = minDataItem.concat(maxDataItem); if (!aDataItems.length) { logger.warn('Could not build minMax Query', this); return oQuerySpec; } oQuerySpec.version = '1'; oQuerySpec.dataItems = aDataItems; oQuerySpec.projections = [minDataItemId, maxDataItemId]; oQuerySpec.limit = queryDefinition.limit || CommonQueryBuilder.getQueryResultsSizeLimit(); if (!queryContext) { return oQuerySpec; } var filters = []; if (queryContext.pageContext) { filters = CommonQueryBuilder.buildFilterFromPageContext(queryContext.pageContext); } oQuerySpec.filters = filters; return oQuerySpec; }; /** * Build minmax query spec. * @param {Object} queryDefinition object that could include dataItems and Projections list etc * @param {Object} queryContext, object that could include pageContent or other query options * @see CommonQueryHelper.whenDataItemsMinMaxQueryReady */ CommonQueryBuilder.buildMinMaxQueryFromDataItems = function buildMinMaxQueryFromDataItems(queryDefinition, queryContext, logger) { var oQuerySpec = {}; if (!queryDefinition.dataItems.length || !queryDefinition.projections.length) { logger.warn('Could not build minMax Query', this); return oQuerySpec; } var oResult = CommonQueryBuilder._getNormalizedItems(queryDefinition, queryContext); // check if any items left after exclusions filtered in _getNormalizedItems if (!oResult.dataItems.length || !oResult.projections.length) { logger.warn('Could not build minMax Query', this); return oQuerySpec; } oQuerySpec.version = '1'; oQuerySpec.dataItems = oResult.dataItems; oQuerySpec.projections = oResult.projections; oQuerySpec.limit = queryDefinition.limit || CommonQueryBuilder.getQueryResultsSizeLimit(); oQuerySpec.type = 'minmax'; if (!queryContext) { logger.warn('Could not build minMax Query with filters', this); return oQuerySpec; } var filters = []; if (queryContext.pageContext) { filters = CommonQueryBuilder.buildFilterFromPageContext(queryContext.pageContext); } oQuerySpec.filters = filters; return oQuerySpec; }; /** * We do not want data items or projections of calculations (from smart annotations) * for min max queries. This method allows us to filter them out. * @param {Array} items objects that may or may not have calculations. * @returns {Array} items that do not have calculations. */ CommonQueryBuilder._getNonCalculationItems = function _getNonCalculationItems(items) { return _.filter(items, function (item) { return item.hasOwnProperty('calculation') === false; }); }; CommonQueryBuilder._getNormalizedItems = function _getNormalizedItems(queryDef, options) { var aDataItemsClone = []; var oDataItemClone; var dataItemsToNormalize = CommonQueryBuilder._getNonCalculationItems(queryDef.dataItems); _.each(dataItemsToNormalize, function (dataItem) { oDataItemClone = _.clone(dataItem); //Remove selection to be consistent R6 delete oDataItemClone.selection; aDataItemsClone.push(oDataItemClone); }); if (!options || !options.itemsToExclude || options.itemsToExclude.length === 0) { return { 'dataItems': aDataItemsClone, 'projections': CommonQueryBuilder._getNonCalculationItems(queryDef.projections) }; } //Continue to normalize query items based on options var aProjectionsClone = _.clone(queryDef.projections); var aItemsToExclude = options.itemsToExclude; aDataItemsClone = _.filter(aDataItemsClone, function (entry) { return aItemsToExclude.indexOf(entry.id) === -1; }); aProjectionsClone = _.filter(aProjectionsClone, function (entry) { return aItemsToExclude.indexOf(entry) === -1; }); return { 'dataItems': aDataItemsClone, 'projections': aProjectionsClone }; }; CommonQueryBuilder._buildBinnedDataItem = function _buildBinnedDataItem(column) { var oDataitem = { 'itemId': column.binningItemId, 'id': column.binningId, 'binning': column.binning }; return oDataitem; }; CommonQueryBuilder._buildDataItems = function _buildDataItems(queryDefinition, logger, queryContext) { var aDataItems = queryDefinition.dataItems || []; if (!aDataItems || !aDataItems.length) { var columns = []; if (queryDefinition.column) { columns.push(queryDefinition.column); } else { logger.warn('No columns or dataItems in the queryDefinition', CommonQueryBuilder); return aDataItems; } _.each(columns, function (column) { var oDataitem; if (column.binning) { oDataitem = CommonQueryBuilder._buildBinnedDataItem(column); } else { oDataitem = { 'id': column.id || column.columnId, 'itemId': column.columnId }; } if (queryDefinition.column.getAggregation && column.columnId === queryDefinition.column.columnId) { oDataitem.aggregate = queryDefinition.column.getAggregation(column); } // If we have a hierarchy with a drill selection, // We need to maintain the drill selection in the column queryContext // This is the case when we show the non numeric filter for hierarchies with drill selections if (queryContext && queryContext.drillSelection) { oDataitem.selection = [queryContext.drillSelection.toJSON()]; } if (queryDefinition.sort) { if (!oDataitem.selection) { oDataitem.selection = []; } oDataitem.selection.push({ 'operation': 'order', 'sort': { 'type': queryDefinition.sort, 'priority': 1 } }); } aDataItems.push(oDataitem); }); } return aDataItems; }; /** * Build function query data items based on functionDefinitions. * @param {Object} queryDefinition - mandatory: the query definitions to build the query spec. * @param {Object} functionDefinitions - mandatory: the function definitions to build the query spec. */ CommonQueryBuilder.buildFunctionQueryDataItems = function buildFunctionQueryDataItems(queryDefinition, functionDefinitions) { var oDataitem = { id: queryDefinition.column.columnId, itemId: queryDefinition.column.columnId }; // Add the function definition var selection = []; var addOperation = { operation: 'add' }; addOperation[functionDefinitions.functionName] = functionDefinitions.functionParameter; selection.push(addOperation); // Add the limit if there is any. if (queryDefinition.limit) { selection.push({ 'operation': 'keep', 'head': queryDefinition.limit }); } oDataitem.selection = selection; return [oDataitem]; }; CommonQueryBuilder.buildProjections = function buildProjections(queryDefinition, logger) { var aProjections = queryDefinition.projections || []; var columns = []; if (!aProjections || !aProjections.length) { if (queryDefinition.column) { columns.push(queryDefinition.column); } if (columns.length === 0 && (!queryDefinition.dataItems || queryDefinition.dataItems.length === 0)) { logger.warn('No columns or projections in the queryDefinition', CommonQueryBuilder); return aProjections; } if (queryDefinition.dataItems) { aProjections.push(queryDefinition.dataItems[0].id); } else { _.each(columns, function (column) { if (column.binning) { aProjections.push(column.binningId); } else { aProjections.push(column.columnId); } }); } } return aProjections; }; CommonQueryBuilder.buildFilterFromPageContext = function buildFilterFromPageContext(pageContext, queryContext, outBinningInfos) { var filters = []; if (_.isEmpty(pageContext)) { return filters; } queryContext = queryContext || {}; _.each(pageContext, function (pageContextItem) { if (!CommonQueryBuilder._processVisiblePageContextItem(pageContextItem, queryContext.visibleItemsMap)) { var filterEntry = CommonQueryBuilder._buildFilterEntryFromPageContext(pageContextItem, queryContext, outBinningInfos); if (filterEntry) { filterEntry = DataQueryUtils.removeForecastFilters(filterEntry); filters.push(filterEntry); } } }); return filters; }; CommonQueryBuilder._processVisiblePageContextItem = function _processVisiblePageContextItem(pageContextEntry, visibleItemsMap) { if (pageContextEntry.origin === 'visualization' && visibleItemsMap) { var nonProjectedHierarchyFound = _.find(pageContextEntry.hierarchies, function (hierarchy) { return visibleItemsMap[hierarchy.hierarchyUniqueName] === undefined; }); //Return true if all items in this visualization entry are projected. return nonProjectedHierarchyFound ? false : true; } return false; }; CommonQueryBuilder._buildFilterEntryFromPageContext = function _buildFilterEntryFromPageContext(contextEntry, queryContext, outBinningInfos) { var filterEntry = void 0; if (contextEntry.exclude && contextEntry.tupleSet && contextEntry.tupleSet.length === 0 && contextEntry.origin === 'filter') { // Convert exclude empty filter to include all filter var hierarchy = contextEntry.hierarchies && contextEntry.hierarchies[0]; // Should always only have one hierarchy in filter dock filters. var newExtraQueryDataItem = queryContext && queryContext.queryOptions && queryContext.queryOptions.addExtraQueryDataItem && queryContext.queryOptions.addExtraQueryDataItem(hierarchy.hierarchyUniqueName); if (newExtraQueryDataItem) { filterEntry = { type: PRE, expression: { operator: IN, itemId: newExtraQueryDataItem.itemId, valueDataItem: newExtraQueryDataItem.id } }; } } else { var filterExpression = CommonQueryBuilder._buildFilterExpressionFromContextEntry(contextEntry, queryContext, outBinningInfos); if (filterExpression && !_.isEmpty(filterExpression)) { filterEntry = {}; filterEntry.type = PRE; // For pageContext, the aggregation type is always preaggregation. filterEntry.expression = contextEntry.exclude ? { 'not': filterExpression } : filterExpression; } } return filterEntry; }; /** // Build filter expression based on each contextEntry. // example of contextEntry with 2 hierarchies: // { // 'origin': 'visualization', // 'table': '', // 'alias': '0', // 'filterName': '', // 'assetId': 'id:/0059b99d-9692-4607-99a5-d682d5858ce8', // 'exclude': false, // 'hierarchies': [ // { // 'hierarchyUniqueName': 'Sheet1.Year_' // }, // { // 'hierarchyUniqueName': 'Sheet1.Order_method_type' // } // ], // 'error': null, // 'tupleSet': [ // [ // { // 'u': '2013' // }, // { // 'u': 'Sales visit' // } // ], // [ // { // 'u': '2012' // }, // { // 'u': 'Fax' // } // ], // [ // { // 'u': '2011' // }, // { // 'u': 'E-mail' // } // ] // ] // } // // The filter expression produced: // [{ // 'type': 'pre', // 'expression': { // 'or': [ // { // 'and': [ // { // 'operator': 'in', // 'itemId': 'Sheet1.Year_', // 'values': [ // '2013' // ] // }, // { // 'operator': 'in', // 'itemId': 'Sheet1.Order_method_type', // 'values': [ // 'Sales visit' // ] // } // ] // }, // { // 'and': [ // { // 'operator': 'in', // 'itemId': 'Sheet1.Year_', // 'values': [ // '2012' // ] // }, // { // 'operator': 'in', // 'itemId': 'Sheet1.Order_method_type', // 'values': [ // 'Fax' // ] // } // ] // }, // { // 'and': [ // { // 'operator': 'in', // 'itemId': 'Sheet1.Year_', // 'values': [ // '2011' // ] // }, // { // 'operator': 'in', // 'itemId': 'Sheet1.Order_method_type', // 'values': [ // 'E-mail' // ] // } // ] // } // ] // } // }] */ CommonQueryBuilder._buildFilterExpressionFromContextEntry = function _buildFilterExpressionFromContextEntry(contextEntry, queryContext, outBinningInfos) { var filterExpression = {}; var hierarchies = contextEntry.hierarchies; var tupleSet = contextEntry.tupleSet; // Single hierarchy case if (hierarchies.length === 1) { if (contextEntry.isModeledFilter) { //Model filter always has only one hierarchy return { filterId: contextEntry.hierarchies[0].hierarchyUniqueName }; } if (tupleSet && tupleSet.length) { filterExpression = CommonQueryBuilder._buildFilterExpressionFromSingleHierarchy(contextEntry, queryContext, outBinningInfos); } else if (contextEntry.conditions && contextEntry.conditions[0]) { var itemId = contextEntry.hierarchies[0].hierarchyUniqueName; if (this._filterIsOnDisplayValue(contextEntry, queryContext, itemId)) { filterExpression.valueType = 'display'; } // page context can contain 1 or 2 values. // depending on which value is missing we generate: // a) between from and to // b) before to // c) after from // unless it's inverted. Then we do the reverse. CommonQueryBuilder.setFilterExpressionId(contextEntry.binningAPIs, contextEntry.hierarchies[0].hierarchyUniqueName, filterExpression, outBinningInfos); var from = contextEntry.conditions[0].from ? contextEntry.conditions[0].from[0] : ''; var to = contextEntry.conditions[0].to ? contextEntry.conditions[0].to[0] : ''; var invert = contextEntry.conditions[0].invert; if (to !== '' && from !== '') { filterExpression.operator = invert ? NOTBETWEEN : BETWEEN; filterExpression.values = [contextEntry.conditions[0].from[0], contextEntry.conditions[0].to[0]]; } else if (from !== '') { filterExpression.operator = invert ? LT : GT; filterExpression.values = [from]; } else if (to !== '') { filterExpression.operator = invert ? GT : LT; filterExpression.values = [to]; } } else { var binningInfo = CommonQueryBuilder.getBinningInfoForDataItem(contextEntry.binningAPIs, hierarchies[0].hierarchyUniqueName); if (!binningInfo) { CommonQueryBuilder.setFilterExpressionId(contextEntry.binningAPIs, hierarchies[0].hierarchyUniqueName, filterExpression, outBinningInfos); CommonQueryBuilder._buildFilterExpressionFromSingleHierarchyNoTupleSet(filterExpression); } } return filterExpression; } // Multiple hierarchies case. var aFilterExpressions = []; _.each(tupleSet, function (tuple) { var filterExpression = CommonQueryBuilder._buildFilterExpressionFromSingleTuple(hierarchies, tuple, contextEntry.binningAPIs, outBinningInfos); if (filterExpression && !_.isEmpty(filterExpression)) { aFilterExpressions.push(filterExpression); } }); // If there are multiple tuples, need to add OR operator. if (aFilterExpressions.length) { filterExpression = tupleSet.length > 1 ? { 'or': aFilterExpressions } : aFilterExpressions[0]; } return filterExpression; }; CommonQueryBuilder._buildFilterExpressionFromSingleHierarchy = function _buildFilterExpressionFromSingleHierarchy(pageContextEntry, queryContext, binningInfos) { var itemId = pageContextEntry.hierarchies[0].hierarchyUniqueName; var filterExpression = void 0; var binningInfo = CommonQueryBuilder.getBinningInfoForDataItem(pageContextEntry.binningAPIs, itemId); if (!binningInfo) { // determine the filter type.... var useDisplayValue = CommonQueryBuilder._filterIsOnDisplayValue(pageContextEntry, queryContext, itemId); var tupleValues = []; _.each(pageContextEntry.tupleSet, function (tuple) { tupleValues.push(useDisplayValue ? tuple[0].d : tuple[0].u); }); // Get rid of the explicit null entries in the values var valuesExcludingNull = _.without(tupleValues, null, 'null'); if (valuesExcludingNull.length > 0) { filterExpression = { operator: IN, values: valuesExcludingNull }; CommonQueryBuilder.setFilterExpressionId(pageContextEntry.binningAPIs, itemId, filterExpression, binningInfos); } if (valuesExcludingNull.length < pageContextEntry.tupleSet.length) { var filterExpressionWithNull = { operator: ISNULL }; CommonQueryBuilder.setFilterExpressionId(pageContextEntry.binningAPIs, itemId, filterExpressionWithNull, binningInfos); if (valuesExcludingNull.length > 0) { var combiningOperator = OR; var combiningExpression = {}; combiningExpression[combiningOperator] = [filterExpressionWithNull, filterExpression]; filterExpression = combiningExpression; } else { filterExpression = filterExpressionWithNull; } } if (filterExpression && useDisplayValue) { filterExpression.valueType = 'display'; } } return filterExpression; }; CommonQueryBuilder.getBinningInfoForDataItem = function getBinningInfoForDataItem(binningAPIs, itemId) { var binningInfo; if (binningAPIs && binningAPIs.length) { binningInfo = binningAPIs.find(function (binningInfo) { return binningInfo.itemId === itemId; }); } return binningInfo; }; CommonQueryBuilder.setFilterExpressionId = function setFilterExpressionId(binningAPIs, itemId, filterExpression, binningInfos) { var binningInfo = CommonQueryBuilder.getBinningInfoForDataItem(binningAPIs, itemId); if (binningInfo) { filterExpression.dataItem = binningInfo.binningAPI.getId(); if (binningInfos) { binningInfos.push(binningInfo); } } else { filterExpression.itemId = itemId; } }; /* add binning dataItem from pagecontext to query */ CommonQueryBuilder.addBinningDataItemIfNeedit = function addBinningDataItemIfNeedit(dataItems, binningInfos) { binningInfos.forEach(function (binningInfo) { var dataItem = dataItems.find(function (dataItem) { return binningInfo.binningAPI.getId() === dataItem.id && binningInfo.itemId === dataItem.itemId; }); if (!dataItem) { var binningSpec = binningInfo.binningAPI.toQueryJSON(); // binningAPI has Binned DataItem label that must not be included in querySpec delete binningSpec.label; binningSpec.itemId = binningInfo.itemId; dataItems.push(binningSpec); } }); }; CommonQueryBuilder._isOlapProperty = function _isOlapProperty(queryContext, itemId) { var mdColumn = queryContext && queryContext.metadataAPI && queryContext.metadataAPI.getMetadataColumn && queryContext.metadataAPI.getMetadataColumn(itemId); return mdColumn && mdColumn.getSourceCategory && mdColumn.getSourceCategory() === 'property' ? true : false; }; CommonQueryBuilder._filterIsOnDisplayValue = function _filterIsOnDisplayValue(pageContextEntry, queryContext, itemId) { return pageContextEntry && pageContextEntry.isSynchronizedEntry || this._isOlapProperty(queryContext, itemId); }; CommonQueryBuilder._buildFilterExpressionFromSingleTuple = function _buildFilterExpressionFromSingleTuple(hierarchies, tuple, binningAPIs, binningInfos) { var aFilterExpressions = []; //Normally, we pass the use values, however; if the tuple is a number (ie: tuplePart.d is a number not a string) //we can't include members. var tupleContainsNumber = _.find(tuple, function (tuplePart) { return _.isNumber(tuplePart.d); }); for (var i = 0; i < hierarchies.length; i++) { var binningInfo = CommonQueryBuilder.getBinningInfoForDataItem(binningAPIs, hierarchies[i].hierarchyUniqueName); if (!binningInfo) { var filterExpression = {}; CommonQueryBuilder.setFilterExpressionId(binningAPIs, hierarchies[i].hierarchyUniqueName, filterExpression, binningInfos); var filterValue = tupleContainsNumber ? tuple[i].d : tuple[i].u; if (filterValue === null) { filterExpression.operator = ISNULL; } else { filterExpression.operator = IN; filterExpression.values = [filterValue]; if (tupleContainsNumber) { filterExpression.valueType = 'display'; } } aFilterExpressions.push(filterExpression); } } return aFilterExpressions.length ? { 'and': aFilterExpressions } : null; }; /** * * @param {Object} filterExpression Filter expression of a full set or a data item. * e.g. * { * "type": "pre", * "expression": { * "operator": "in", * "itemId": "[Automobile_C01].[RGB Colors]", * "valueDataItem": "[Automobile_C01].[RGB Colors]" * } * } */ CommonQueryBuilder._buildFilterExpressionFromSingleHierarchyNoTupleSet = function _buildFilterExpressionFromSingleHierarchyNoTupleSet(filterExpression) { filterExpression.operator = IN; filterExpression.valueDataItem = filterExpression.itemId ? filterExpression.itemId : filterExpression.dataItem; }; CommonQueryBuilder._buildFilterFromSearchTerm = function _buildFilterFromSearchTerm(specOption, searchTerm) { if (!_.isArray(searchTerm) && !_.isString(searchTerm)) { throw new Error('Invalid searchTerm'); } var isArray = _.isArray(searchTerm); var values = isArray ? searchTerm : [searchTerm]; var filter = { 'type': PRE, 'expression': { 'itemId': specOption.column.columnId, 'values': values } }; if (isArray) { filter.expression.operator = IN; filter.expression.ignoreCase = true; filter.expression.valueType = 'display'; } else { filter.expression.operator = CONTAINSIGNORECASE; } return [filter]; }; CommonQueryBuilder.getQueryResultsSizeLimit = function getQueryResultsSizeLimit() { return QUERY_RESULTS_SIZE_LIMIT; }; CommonQueryBuilder.addExtraQueryDataItem = function addExtraQueryDataItem(uniqueDataItemIdsMap, queryOptions, itemId) { var extraDataItems = queryOptions.extraDataItems || []; if (_.pluck(extraDataItems, 'itemId').indexOf(itemId) === -1) { var uniqueId = UniqueHashIdBuilder.createUniqueHashId(itemId, uniqueDataItemIdsMap); var random = 0; var extraDataItemIds = _.pluck(extraDataItems, 'id'); while (extraDataItemIds.indexOf(uniqueId) !== -1) { uniqueId = UniqueHashIdBuilder.createUniqueHashId(itemId + random++, uniqueDataItemIdsMap); } var extraQueryDataItem = { id: uniqueId, itemId: itemId }; extraDataItems.push(extraQueryDataItem); queryOptions.extraDataItems = extraDataItems; return extraQueryDataItem; } }; return CommonQueryBuilder; }(); return CommonQueryBuilder; }); //# sourceMappingURL=CommonQueryBuilder.js.map