| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 | 'use strict';/* *+------------------------------------------------------------------------+ *| Licensed Materials - Property of IBM *| IBM Cognos Products: BI 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/core-client/js/core-client/ui/core/Class', '../../../lib/@waca/upgrades/UpgradeBase',// Ughn - this file should not be in dashboard-core... with dependencies on livewidget...'dashboard-analytics/dataSources/models/DataSourcesModel', 'dashboard-analytics/dataSources/services/DataSourcesService'], function (_, Class, UpgradeBase, DataSourcesModel, DataSourcesService) {	//NOSONAR	var UpgradeShaping = Class.extend([UpgradeBase], {		init: function init() {			this.VERSION = 1005;		},		ORIGIN_VISUALIZATION: 'visualization',		ORIGIN_FILTER: 'filter',		/**   * Perform upgrade   *   * @param {object} spec - spec to perform upgrade on   *   * @return {Promise} Promise to be resolved when upgrade performed   */		up: function up(spec) {			this._calcIdMap = {};			this.dataSourcesService = null;			this._eventGroupMap = {};			this._assetIdMap = {};			this.spec = spec;			this.dataSourcesService = new DataSourcesService({				features: {					API: this.data.dashboardApi,					Logger: this.data.logger				}			});			this.spec.dataSources = new DataSourcesModel(this.spec.dataSources);			var dataSetShapingsToUpgrade = _.filter(this.spec.datasetShaping, function (datasetShapingInst) {				return datasetShapingInst.calculations.length;			});			this._buildEventGroupMap();			return this._upgradeShaping(dataSetShapingsToUpgrade).then(this._upgradeFilters.bind(this)).then(this._upgradeShapingFilters.bind(this)).then(function () {				this._updateWidgetCalculationReferences();				// remove old shaping				delete this.spec.datasetShaping;				// For pin upgrade with need the JSON back, not the object				if (this.data.pinUpgrade) {					if (this.spec.dataSources.toJSON) {						this.spec.dataSources = this.spec.dataSources.toJSON();					}					// Cleanup any temp modules that were created					this.dataSourcesService.destroy();				}				Promise.resolve(this.spec);			}.bind(this), function (failure) {				if (this.data.pinUpgrade) {					// Cleanup any temp modules that were created					this.dataSourcesService.destroy();				}				throw failure;			});		},		/**   * @returns container Page id containing the layout id   * @param    widgetId   */		getContainerPageId: function getContainerPageId(id) {			var topParent = this.findTopLevelParentItem(this.spec.layout, id);			if (topParent) {				return topParent.id;			}			return undefined;		},		/**   * Given any layout item, find its top level parent item (the item in the layout’s root level item list that contains it).   * @param layout - this is the layout specification in the board spec   * @param id - the id of the model for a widget   * @returns the parent object (ie tab) for this model id   */		findTopLevelParentItem: function findTopLevelParentItem(layout, id) {			var itemFound = null;			_.each(layout.items, function (item) {				if (item.id === id) {					itemFound = layout;				} else if (this.findChildItem(item.items, id) !== null) {					itemFound = item;				}			}.bind(this));			return itemFound;		},		/**   * Recursively search all layout items and their child items lists for an id which matches   * the specified id   * @param items - the items list whose subtree of items lists are to be searched   * @param id - the id to search for.   * @returns the item if found or null if this id does not exist in this items list or any child lists.   */		findChildItem: function findChildItem(items, id) {			if (!items) {				return null;			}			var result = null;			for (var i = 0; i < items.length; ++i) {				var item = items[i];				if (item.id === id) {					// found it!					result = item;					break;				} else if (item.items) {					item = this.findChildItem(item.items, id);					if (item) {						// found it!						result = item;						break;					}					// otherwise continue with the remaining siblings				}			}			return result;		},		_buildEventGroupMap: function _buildEventGroupMap() {			_.each(this.spec.eventGroups, function (eg) {				_.each(eg.widgetIds, function (wIds) {					this._eventGroupMap[wIds] = eg.id;				}.bind(this));			}.bind(this));		},		_upgradeFilters: function _upgradeFilters() {			try {				var pageContextMap = {};				var promises = [];				_.each(this.spec.widgets, function (widget) {					var modelRef = widget && widget.data && widget.data.dataViews[0] ? widget.data.dataViews[0].modelRef : null;					if (modelRef) {						var sourceSpec = _.find(this.spec.dataSources.sources.models, function (source) {							return source.id === modelRef;						});						promises.push(this._getModule(sourceSpec, false).then(function (module) {							if (!this.spec.pageContext) {								this.spec.pageContext = [];							}							if (!_.isEmpty(widget.filters)) {								this._buildPageContext(module, pageContextMap, widget, sourceSpec.id);								delete widget.filters;							}							if (!_.isEmpty(widget.localFilters)) {								this._updateLocalFilters(module, widget.localFilters);							}						}.bind(this)));					}				}.bind(this));				return Promise.all(promises).then(function () {					if (!_.isEmpty(pageContextMap)) {						this.spec.pageContext = _.values(pageContextMap);					}				}.bind(this));			} catch (error) {				throw error;			}		},		_upgradeShapingFilters: function _upgradeShapingFilters() {			try {				var pageContextMap = {};				var promises = [];				_.each(this.spec.datasetShaping, function (shaping) {					var sourceSpec = _.find(this.spec.dataSources.sources.models, function (source) {						return source.assetId === shaping.id;					});					if (sourceSpec) {						promises.push(this._getModule(sourceSpec, false).then(function (module) {							if (!this.spec.pageContext) {								this.spec.pageContext = [];							}							if (!_.isEmpty(shaping.filters)) {								this._addShapingFiltersToPageContext(module, pageContextMap, shaping, sourceSpec.id);							}							delete shaping.filters;						}.bind(this)));					}				}.bind(this));				return Promise.all(promises).then(function () {					if (!_.isEmpty(pageContextMap)) {						this.spec.pageContext = this.spec.pageContext.concat(_.values(pageContextMap));					}				}.bind(this));			} catch (error) {				throw error;			}		},		_updateLocalFilters: function _updateLocalFilters(module, filters) {			try {				_.each(filters, function (filter) {					if (filter.values) {						if (filter.values[0] && _.isObject(filter.values[0]) && !filter.values[0].operator) {							this._updateFilterUseValues(module, filter, 'object');						} else if (filter.values[0] && typeof filter.values[0] === 'string') {							this._updateFilterUseValues(module, filter, 'string');						} else if (!filter.values[0]) {							this._updateFilterUseValues(module, filter, 'null');						} else {							this._updateLocalFilters(module, filter.values);						}					}				}.bind(this));			} catch (error) {				throw error;			}		},		_addShapingFiltersToPageContext: function _addShapingFiltersToPageContext(module, pageContextMap, shape, sourceId) {			_.each(shape.filters, function (filter) {				var mappedProps = this._createTuplesAndHierarchies(module, filter, this.ORIGIN_FILTER);				var pageContext = {					'origin': this.ORIGIN_FILTER,					'table': '',					'alias': '',					'sourceId': sourceId,					'scope': 'global',					'hierarchyNames': mappedProps.hierarchyNames,					'hierarchyUniqueNames': mappedProps.hierarchies				};				if (filter.operator === 'between' || filter.operator === 'notbetween' || filter.operator === 'lt' || filter.operator === 'gt') {					pageContext.conditions = this._createCondition(filter);				} else {					if (filter.operator === 'notin') {						pageContext.exclude = true;					}					pageContext.tupleSet = mappedProps.tupleSet;				}				var uniqueKey = mappedProps.key + pageContext.scope + pageContext.sourceId;				if (_.isEmpty(pageContextMap[uniqueKey])) {					pageContextMap[uniqueKey] = pageContext;				}			}.bind(this));		},		_buildPageContext: function _buildPageContext(module, pageContextMap, widget, sourceId) {			_.each(widget.filters, function (filter) {				var mappedProps = this._createTuplesAndHierarchies(module, filter, this.ORIGIN_VISUALIZATION);				var pageContext = {					'origin': this.ORIGIN_VISUALIZATION,					'table': '',					'alias': '',					'tupleSet': mappedProps.tupleSet,					'sourceId': sourceId,					'hierarchies': mappedProps.hierarchyList,					'hierarchyUniqueNames': mappedProps.hierarchies,					'scope': this.getContainerPageId(widget.id),					'eventSourceId': widget.id,					'eventGroupId': this._eventGroupMap[widget.id]				};				var uniqueKey = mappedProps.key + pageContext.eventGroupId + pageContext.scope + pageContext.sourceId;				if (_.isEmpty(pageContextMap[uniqueKey])) {					pageContextMap[uniqueKey] = pageContext;				}			}.bind(this));		},		_createCondition: function _createCondition(filter) {			var condition = {				from: '',				to: '',				attributeUniqueNames: [filter.columnId]			};			if (filter.operator === 'between' || filter.operator === 'notbetween') {				condition.from = [filter.values[0].d || filter.values[0].displayValue || filter.values[0]];				condition.to = [filter.values[1].d || filter.values[1].displayValue || filter.values[1]];			} else if (filter.operator === 'lt') {				condition.to = [filter.values[0].d || filter.values[0].displayValue || filter.values[0]];			} else {				condition.from = [filter.values[0].d || filter.values[0].displayValue || filter.values[0]];			}			if (filter.operator === 'notbetween') {				condition.invert = true;			}			return [condition];		},		_createTuplesAndHierarchies: function _createTuplesAndHierarchies(module, filter, origin) {			var properties;			switch (filter.operator) {				case 'in':				case 'notin':				case 'isnull':				case 'between':				case 'notbetween':				case 'lt':				case 'gt':					this._updateFilterUseValues(module, filter);					properties = this._buildEdgeFilterTupleSet(module, filter, origin);					break;				case 'or':				case 'not':					properties = this._buildDataPointFilterTupleSet(module, filter, origin);					break;				default:					properties = {						'tupleSet': '',						'hierachyList': '',						'hierarchies': ''					};					break;			}			return properties;		},		_getMetadataColumn: function _getMetadataColumn(module, columnId) {			return module ? module.getMetadataColumn(columnId) : null;		},		_getMetadataColumnLabel: function _getMetadataColumnLabel(mdColumn) {			return mdColumn ? mdColumn.getLabel() : null;		},		isFacetEnabled: function isFacetEnabled(mdColumn) {			var facetDefinition = mdColumn && mdColumn.getFacetDefinition ? mdColumn.getFacetDefinition() : null;			return facetDefinition && facetDefinition.enabled && facetDefinition.enabled.enumValue !== 'false' ? true : false;		},		isOlapPackage: function isOlapPackage(mdColumn) {			var retval = false;			if (mdColumn) {				var sourceCategory = mdColumn.getSourceCategory();				retval = sourceCategory && sourceCategory !== 'column' && mdColumn.getObjectType() === 'QueryItem';			}			return retval;		},		_isDateOrTimeValue: function _isDateOrTimeValue(dateStr) {			return isNaN(dateStr) && !isNaN(Date.parse(dateStr));		},		_isDateOrTime: function _isDateOrTime(metadata, value) {			return metadata && metadata.isDateOrTimeType() && this._isDateOrTimeValue(value);		},		_isRangeOperator: function _isRangeOperator(operator) {			return operator && (operator === 'between' || operator === 'notbetween' || operator === 'lt' || operator === 'gt');		},		_isRangeFilter: function _isRangeFilter(metadataColumn, filter, value) {			return this._isRangeOperator(filter.operator) && (_.isNumber(value) || this._isDateOrTime(metadataColumn, value));		},		_updateFilterUseValues: function _updateFilterUseValues(module, filter, type) {			var metadataColumn = this._getMetadataColumn(module, filter.columnId);			var facetEnabled = this.isFacetEnabled(metadataColumn);			var isOlap = this.isOlapPackage(metadataColumn);			if (filter && filter.values) {				var updateValuesList = [];				_.each(filter.values, function (value) {					var mappedObj = {};					if (type === 'string') {						mappedObj.u = value;						mappedObj.d = value;					} else if (type === 'null') {						mappedObj = null;					} else {						mappedObj.u = !facetEnabled || isOlap || this._isRangeFilter(metadataColumn, filter, value.useValue) || value.useValue === null ? value.useValue : this._mapUseValue(filter.columnId, value.useValue);						mappedObj.d = value.displayValue;					}					updateValuesList.push(mappedObj);				}.bind(this));				delete filter.values;				filter.values = updateValuesList;			}		},		_mapUseValue: function _mapUseValue(hun, value) {			value = typeof value === 'string' ? value.replace(/]/g, ']]') : value;			return hun + '->' + '[' + value + ']';		},		_buildEdgeFilterTupleSet: function _buildEdgeFilterTupleSet(module, filter, origin) {			var hunKey = '';			var tupleSet = {};			var hierarchyList = [];			var hierarchies = [];			var hierarchyNames = [];			if (origin === this.ORIGIN_FILTER) {				hierarchyNames.push(this._getMetadataColumnLabel(this._getMetadataColumn(module, filter.columnId)));			} else {				hierarchyList.push({					'hierarchyUniqueName': filter.columnId				});			}			_.each(filter.values, function (value) {				tupleSet[value.u] = value;				hunKey += filter.columnId;				hierarchies.push(filter.columnId);			});			var filterProps = {};			filterProps.tupleSet = JSON.stringify(tupleSet);			filterProps.hierarchies = _.uniq(hierarchies);			filterProps.key = hunKey;			if (origin === this.ORIGIN_FILTER) {				filterProps.hierarchyNames = hierarchyNames;			} else if (origin === this.ORIGIN_VISUALIZATION) {				filterProps.hierarchyList = hierarchyList;			}			return filterProps;		},		_buildDataPointFilterTupleSet: function _buildDataPointFilterTupleSet(module, filter) {			var hunKey = '';			var tupleSet = {};			var hierarchyList = [];			var hierarchies = [];			if (filter.values) {				_.each(filter.values, function (filters) {					if (filters.operator === 'and') {						this._buildAndFilterTuple(module, tupleSet, hierarchyList, filters);					}				}.bind(this));			}			hierarchyList = _.uniq(hierarchyList);			_.each(hierarchyList, function (h) {				hierarchies.push({					'hierarchyUniqueName': h				});				hunKey += h;			});			return {				'tupleSet': JSON.stringify(tupleSet),				'hierarchyList': _.uniq(hierarchies),				'hierarchies': _.uniq(hierarchyList),				'key': hunKey			};		},		_buildAndFilterTuple: function _buildAndFilterTuple(module, tupleSet, hierarchyList, filter) {			var tupleKey = '';			var tupleValues = [];			_.each(filter.values, function (value) {				this._updateFilterUseValues(module, value);				_.each(value.values, function (value) {					tupleKey += value.u;					tupleValues.push(value);				}.bind(this));				hierarchyList.push(value.columnId);			}.bind(this));			tupleSet[tupleKey] = tupleValues;		},		_upgradeShaping: function _upgradeShaping(datasetShapingsToUpgrade) {			try {				var datasetShapingInst = datasetShapingsToUpgrade.shift();				if (datasetShapingInst) {					return this._upgradeShapingInstance(datasetShapingInst).then(function () {						this.spec.queriedForUpgrade = true;						return this._upgradeShaping(datasetShapingsToUpgrade);					}.bind(this));				} else {					return Promise.resolve(true);				}			} catch (error) {				throw error;			}		},		_getSourcesCollection: function _getSourcesCollection(dataSourceModel) {			var sourcesCollection = this.dataSourcesService.getSourcesCollection(dataSourceModel);			return sourcesCollection.getSources();		},		_getModule: function _getModule(sourceSpec, forceTemp) {			if (!sourceSpec) {				throw new Error('Could not find source specfication');			}			if (forceTemp === true) {				sourceSpec.useTempModule = true;			}			var sources = this._getSourcesCollection(this.spec.dataSources);			var existingSource = _.find(sources, function (source) {				return source.getAssetId() === sourceSpec.assetId;			});			if (!existingSource) {				throw new Error('Could not find source module');			} else {				var showErrorToast = typeof this.data.showErrorToast === 'undefined' ? true : this.data.showErrorToast;				return existingSource.getModule(null, showErrorToast);			}		},		_upgradeShapingInstance: function _upgradeShapingInstance(datasetShapingInst) {			try {				var sourceSpec = _.find(this.spec.dataSources.sources.models, function (source) {					return source.assetId === datasetShapingInst.id;				});				if (!sourceSpec) {					return Promise.resolve(true);				}				return this._getModule(sourceSpec, true).then(function (module) {					return this._addCalculation(module, datasetShapingInst.calculations);				}.bind(this), function (failure) {					if (this.data.pinUpgrade) {						// Cleanup any temp modules that were created						this.dataSourcesService.destroy();					}					throw failure;				}.bind(this));			} catch (error) {				throw error;			}		},		_addCalculation: function _addCalculation(module, calculations) {			var calculation = calculations.shift();			if (calculation) {				// For percent change, the new opereation to use is ¢				var operation = calculation.expr.op === '%d' ? '¢' : calculation.expr.op;				var calcProperties = {					inputtedName: calculation.label,					operation: operation,					elementOperands: [],					numberOperands: []				};				_.each(calculation.expr.params, function (param) {					var metaDataColumn = module.getMetadataColumn(this._calcIdMap[param.col] || param.col);					calcProperties.elementOperands.push(metaDataColumn.moserObject);				}.bind(this));				// For old % change calculation we need to reverse the array of data items or we won't get the same numbers as in R6.				if (operation === '¢') {					calcProperties.elementOperands.reverse();				}				return module.addCalculation(calcProperties).then(function (newCalculationId) {					this._calcIdMap[calculation.id] = newCalculationId;					return this._addCalculation(module, calculations);				}.bind(this));			} else {				return Promise.resolve(true);			}		},		_updateWidgetCalculationReferences: function _updateWidgetCalculationReferences() {			try {				_.each(this.spec.widgets, function (widget) {					var dataViews = widget.data && widget.data.dataViews ? widget.data.dataViews : [];					_.each(dataViews, function (dataView) {						_.each(dataView.dataItems, function (dataItem) {							dataItem.itemId = this._calcIdMap[dataItem.itemId] || dataItem.itemId;						}.bind(this));					}.bind(this));					_.each(widget.localFilters, function (localFilter) {						localFilter.columnId = this._calcIdMap[localFilter.columnId] || localFilter.columnId;					}.bind(this));				}.bind(this));			} catch (error) {				throw error;			}		},		down: function down(spec) {			return Promise.resolve(spec);		}	});	return new UpgradeShaping();});//# sourceMappingURL=waca_shaping.js.map
 |