'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: BI Cloud (C) Copyright IBM Corp. 2019, 2021 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['../../../lib/@waca/dashboard-common/dist/core/APIFactory', './api/QueryProviderAPI', '../../../filters/FilterQuerySpec', '../../../apiHelpers/SlotAPIHelper', './QueryDataItemBuilder', './DataQueryUtils', '../../../lib/@waca/core-client/js/core-client/utils/BrowserUtils', '../../../widgets/livewidget/query/CommonQueryBuilder', 'underscore'], function (APIFactory, QueryProviderAPI, FilterQuerySpec, SlotAPIHelper, QueryDataItemBuilder, DataQueryUtils, BrowserUtils, CommonQueryBuilder, _) { var _class, _temp; var QueryProvider = (_temp = _class = function () { function QueryProvider(_ref) { var content = _ref.content, dashboardAPI = _ref.dashboardAPI; _classCallCheck(this, QueryProvider); this.content = content; this.dashboard = dashboardAPI; this.content.getFeature('DataQueryExecution').registerQueryProvider(this.getAPI()); } QueryProvider.prototype.getAPI = function getAPI() { if (!this.api) { this.api = APIFactory.createAPI(this, [QueryProviderAPI]); } return this.api; }; QueryProvider.prototype.getType = function getType() { return 'main'; }; /** * @returns a list of query specs. */ QueryProvider.prototype.getQuerySpecList = function getQuerySpecList() { var _this = this; var visualization = this.content.getFeature('Visualization'); var dataSource = visualization.getDataSource(); var dataSourceId = dataSource && dataSource.getId(); var mappedSlotsList = visualization.getSlots().getMappedSlotList(); var layerToQuerySlotsMap = new Map(); var mappingCompleteLayerList = this._getMappingCompleteLayers() || []; var _loop = function _loop(i) { var slot = mappedSlotsList[i]; if (_this._canQuery(slot)) { var layerIds = slot.getDefinition().getDatasetIdList(); layerIds.forEach(function (layerId) { if (mappingCompleteLayerList.indexOf(layerId) === -1) { //skip the layer if the required slots for that layer are NOT filled return; } if (!layerToQuerySlotsMap.has(layerId)) { layerToQuerySlotsMap.set(layerId, []); } layerToQuerySlotsMap.get(layerId).push(slot); }); } }; for (var i = 0; i < mappedSlotsList.length; i++) { _loop(i); } var querySpecList = []; var mainQuerySpecList = this._getMainQuerySpecList(layerToQuerySlotsMap); querySpecList.push.apply(querySpecList, mainQuerySpecList); querySpecList.push.apply(querySpecList, this._getMinMaxQuerySpecList(layerToQuerySlotsMap, mainQuerySpecList)); for (var j = 0; j < querySpecList.length; j++) { querySpecList[j].dataSourceId = dataSourceId; } return querySpecList; }; QueryProvider.prototype._getMappingCompleteLayers = function _getMappingCompleteLayers() { var visualization = this.content.getFeature('Visualization'); var datasetIds = visualization.getDefinition().getDatasetList().map(function (dataset) { return dataset.id; }); var slots = visualization.getSlots(); return datasetIds.filter(function (id) { return slots.isMappingComplete(id); }); }; QueryProvider.prototype._getQuerySpecLimit = function _getQuerySpecLimit() { //DEFAULT limit var dataRowLimit = QueryProvider.DEFAULT_ROWLIMIT; var definition = this.content.getFeature('Visualization').getDefinition(); if (definition.getProperty('dataRowLimit')) { //Some charts have difficulty rendering a large set of rows, in this case, a smaller dataRowLimit is set in the definition. dataRowLimit = definition.getProperty('dataRowLimit'); // Reduce data limit on IE if (BrowserUtils.isIE() && definition.getProperty('dataRowLimitIE')) { dataRowLimit = definition.getProperty('dataRowLimitIE'); } } return dataRowLimit; }; QueryProvider.prototype._getMainQuerySpecList = function _getMainQuerySpecList(layerToQuerySlotsMap) { var _this2 = this; var queryDataItemBuilder = this._getQueryDataItemBuilder(layerToQuerySlotsMap); var querySpecList = []; var outputEdgeFilterExceptions = []; var queryHints = this._getQueryHints(layerToQuerySlotsMap); layerToQuerySlotsMap.forEach(function (querySlots, layerId) { var specObject = { id: layerId, type: 'main', spec: { version: '1', dataItems: [], projections: [], limit: _this2._getQuerySpecLimit() } }; querySlots.forEach(function (slot) { var _specObject$spec$proj, _specObject$spec$data; (_specObject$spec$proj = specObject.spec.projections).push.apply(_specObject$spec$proj, _this2._getProjectionsForSlot(slot)); (_specObject$spec$data = specObject.spec.dataItems).push.apply(_specObject$spec$data, _this2._getDataItemsForSlot(slot, queryDataItemBuilder, outputEdgeFilterExceptions)); }); var excludeNonProjectedRangeFilters = DataQueryUtils.shouldExcludeNonProjectedRangeFilters(layerToQuerySlotsMap, layerId); var filters = _this2._getFilters(layerId, outputEdgeFilterExceptions, excludeNonProjectedRangeFilters); if (filters && filters.length) { specObject.spec.filters = filters; } /** * @todo: useAPI. should check for empty queryHints. * but for now we reserve the same behavior as current that it includes empty queryHints. * if (_.keys(queryHints).length) { specObject.spec.queryHints = queryHints; } */ specObject.spec.queryHints = queryHints; var suppression = _this2._getSuppression(); if (suppression) { specObject.spec.suppress = [suppression]; } querySpecList.push(specObject); }); return querySpecList; }; QueryProvider.prototype._findDataItemInSlotsById = function _findDataItemInSlotsById(slots, id) { var _dataItem = void 0; slots.forEach(function (slot) { slot.getDataItemList().forEach(function (dataItem) { if (dataItem.getId() === id) { _dataItem = dataItem; } }); }); return _dataItem; }; QueryProvider.prototype._getMinMaxQuerySpecList = function _getMinMaxQuerySpecList(layerToQuerySlotsMap, mainQuerySpecList) { var _this3 = this; var minMaxQuerySpecList = []; var shouldAxisScaleBeFixed = this.content.getPropertyValue('maintainAxisScales'); layerToQuerySlotsMap.forEach(function (querySlots, layerId) { var containsCategorySlots = !!querySlots.find(function (slot) { return slot.getDataItemList()[0].getType() === 'attribute'; }); if (shouldAxisScaleBeFixed && containsCategorySlots) { var mainQuerySpecObj = mainQuerySpecList.find(function (obj) { return obj.id === layerId; }); var projectionsAndDataItems = { dataItems: mainQuerySpecObj.spec.dataItems, limit: mainQuerySpecObj.spec.limit }; var minMaxProjections = JSON.parse(JSON.stringify(mainQuerySpecObj.spec.projections)); minMaxProjections = minMaxProjections.filter(function (id) { var dataItem = _this3._findDataItemInSlotsById(querySlots, id); return dataItem && dataItem.getType() === 'fact'; }); // No need for a minmax query when no measures are projected if (minMaxProjections && minMaxProjections.length) { projectionsAndDataItems.projections = minMaxProjections; var aItemsToExclude = []; querySlots.forEach(function (slot) { if (slot.getDefinition().getProperty('useInTopBottomQueries') === false) { aItemsToExclude = aItemsToExclude.concat(slot.getDataItemList().map(function (dataItem) { return dataItem.getId(); })); } else if (slot.isStacked()) { // If the slot is stacked and has multiple data items then we can not add it to the min max query // In this scenario the slot is shown as a nested set of data items and we need to remove using the id. aItemsToExclude = aItemsToExclude.concat(slot.getId()); } }); // Make one query to get min and max only with the fields from the current widget, plus the global filters and slicers (filters from other widgets). var topBottomQuery = CommonQueryBuilder.buildMinMaxQueryFromDataItems(projectionsAndDataItems, { 'itemsToExclude': aItemsToExclude }, _this3.dashboard.getGlassCoreSvc('.Logger')); minMaxQuerySpecList.push({ id: layerId, type: 'minmax', spec: topBottomQuery }); } } }); return minMaxQuerySpecList; }; QueryProvider.prototype._canQuery = function _canQuery(slot) { // If the slot has a multimeasure series item and // it is the one and only item in the slot, we can't generate a query from the slot. return !(SlotAPIHelper.isMultiMeasuresSeriesSlot(slot) && !slot.isStacked()); }; QueryProvider.prototype._isSlotWithStackedProjection = function _isSlotWithStackedProjection(slot) { // if the slot contains at least 2 items(except multi-measure) and it is stacked(slotDefinition) var validDataItems = SlotAPIHelper.getValidDataItems(slot); return slot.isStacked() && validDataItems.length > 1; }; /** * return the projections for the specified slot * @param {*} querySlot queriable slot */ QueryProvider.prototype._getProjectionsForSlot = function _getProjectionsForSlot(querySlot) { if (this._isSlotWithStackedProjection(querySlot)) { return [querySlot.getId()]; } else { var validDataItems = SlotAPIHelper.getValidDataItems(querySlot); return validDataItems.map(function (dataItem) { return dataItem.getId(); }); } }; /** * return the dataItems for the specified slot * @param {*} querySlot queriable slot * @param {*} queryDataItemBuilder */ QueryProvider.prototype._getDataItemsForSlot = function _getDataItemsForSlot(querySlot, queryDataItemBuilder, outputEdgeFilterExceptions) { var validDataItems = SlotAPIHelper.getValidDataItems(querySlot); var dataItemQuerySpecs = validDataItems.map(function (dataItem) { var itemSpec = queryDataItemBuilder.build(dataItem, querySlot, outputEdgeFilterExceptions); return itemSpec; }); if (this._isSlotWithStackedProjection(querySlot)) { dataItemQuerySpecs.push({ id: querySlot.getId(), nest: validDataItems.map(function (item) { return item.getId(); }) }); } return dataItemQuerySpecs; }; QueryProvider.prototype._getQueryDataItemBuilder = function _getQueryDataItemBuilder(layerToQuerySlotsMap) { var internalVisualization = this.content.getFeature('Visualization.internal'); var dataItemList = internalVisualization.getSlots().getDataItemList(); var applyServerSort = dataItemList && _.find(dataItemList, function (dataItem) { return dataItem.getColumnId() === '_multiMeasuresSeries'; }) !== undefined; return new QueryDataItemBuilder({ internalVisualization: internalVisualization, layerToQuerySlotsMap: layerToQuerySlotsMap, applyServerSort: applyServerSort }); }; QueryProvider.prototype._getFilters = function _getFilters(layerId, outputEdgeFilterExceptions, excludeNonProjectedRangeFilters) { var internalVisualization = this.content.getFeature('Visualization.internal'); var localFilterList = internalVisualization.getLocalFilters().getFilterList(); var updatedFilterSpecList = DataQueryUtils.convertExcludeEmptyValuesFilters(localFilterList, internalVisualization.getDataSource()); var searchFilters = internalVisualization.getSearchFilterList(); var filterSpec = new FilterQuerySpec(internalVisualization); var hasSharedSlot = !!internalVisualization.getDefinition().getSlotList().find(function (slot) { return slot.getDatasetIdList().length > 1; }); filterSpec.addFiltersToSpec(updatedFilterSpecList, { layerId: layerId, edgeFilterExceptions: outputEdgeFilterExceptions, excludeNonProjectedRangeFilters: excludeNonProjectedRangeFilters, projectInAllLayers: hasSharedSlot }); filterSpec.addFiltersToSpec(searchFilters, { layerId: layerId }); return filterSpec.hasFilterSpec() ? filterSpec.getFilterSpec() : null; }; /** * Turn on multiEdgeSort based on following rules: * 1: if slot is isMultiMeasuresSeries and is Rank, does not consider as edge * 2: if slot is isMultiMeasuresSeries and is stacked, considered as one edge * 3: if slot is stacked, it is considered as one edge * 4: if slot is of type ordinal, does not consider as edge * if number of edges is more than one, then turn on multiEdgeSort otherwise not * @return {boolean} true if number of edges to sort is more than 1. * @private */ QueryProvider.prototype._isMultiEdgeSortNeeded = function _isMultiEdgeSortNeeded(layerToQuerySlotsMap) { var visualization = this.content.getFeature('Visualization'); if (!visualization.getDefinition().getMultiEdgeSort()) { return false; } var numberOfEdges = 0; layerToQuerySlotsMap.forEach(function (querySlots) { querySlots.forEach(function (slot) { var dataItems = slot.getDataItemList(); if (dataItems.length > 0 && dataItems[0].getType() !== 'fact') { numberOfEdges++; } }); }); return numberOfEdges > 1; }; QueryProvider.prototype._getSuppression = function _getSuppression() { var suppression = this.content.getPropertyValue('suppression'); if (suppression === QueryProvider.SUPPRESSION_NONE) { return QueryProvider.SUPPRESSION_NONE; } }; QueryProvider.prototype._getQueryHints = function _getQueryHints(layerToQuerySlotsMap) { var queryHints = {}; var suppression = this._getSuppression(); if (suppression) { queryHints.suppress = suppression; } if (this._isMultiEdgeSortNeeded(layerToQuerySlotsMap)) { queryHints.multiEdgeSort = true; } var refreshProperty = this.content.getPropertyValue('queryRefresh'); if (refreshProperty && refreshProperty.autoRefresh) { // Set the dataCacheExpiry to 40% of the refresh time var refreshValue = refreshProperty.value; var dataCacheExpiryValue = void 0; switch (refreshProperty.unit) { case 'seconds': dataCacheExpiryValue = parseInt(refreshValue * 4 / 10) || 1; break; case 'minutes': dataCacheExpiryValue = parseInt(refreshValue * 60 * 4 / 10) || 1; break; case 'hours': dataCacheExpiryValue = parseInt(refreshValue * 3600 * 4 / 10) || 1; break; default: dataCacheExpiryValue = 1; } queryHints.dataCacheExpiry = dataCacheExpiryValue.toString(); queryHints.autoRefreshTime = '' + Date.now(); } return queryHints; }; return QueryProvider; }(), _class.DEFAULT_ROWLIMIT = 3000, _class.SUPPRESSION_NONE = 'none', _temp); return QueryProvider; }); //# sourceMappingURL=QueryProvider.js.map