'use strict'; /** * Licensed Materials - Property of IBM * IBM Watson Analytics (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(['../../lib/@waca/core-client/js/core-client/ui/core/Class', 'bi/moser/moser.min', '../../lib/@waca/core-client/js/core-client/i18n/V5Formatter'], function (Class, MoserJS, FormatUtils) { 'use strict'; var UNKNOWN_AGGREGATE_TYPE = 'unknown'; var DATA_TYPE_MAP = { 'BIGINT': 'integer', 'CHAR(': 'string', 'DATE': 'date', 'DATETIME': 'datetime', 'DECIMAL': 'decimal', 'DOUBLE': 'double', 'FLOAT': 'float', 'INTEGER': 'integer', 'NCHAR': 'string', 'NVARCHAR(': 'string', 'SMALLINT': 'integer', 'TIMESTAMP': 'datetime', 'TIME': 'time', 'TINYINT': 'integer', 'LONG': 'integer', 'VARCHAR(': 'string', 'STRING': 'string' }; var SORT_ASCENDING = 'asc'; var SORT_DESCENDING = 'desc'; var MetadataColumn = Class.extend({ /** * @param {Object} options.moserJSColumn */ init: function init(options) { MetadataColumn.inherited('init', this, arguments); this.moserObject = options.moserObject; this.sourceId = options.sourceId; this.queryService = options.queryService; this.propertyOverride = this.getPropertyOverride(); Object.defineProperty(this, 'type', { get: function get() { return this.getType(); } }); Object.defineProperty(this, 'dataType', { get: function get() { return this.getDataType(); } }); Object.defineProperty(this, 'label', { get: function get() { return this.getLabel(); } }); // leaf and non-leaf member cache used to avoid second getChildren() call for a member within same session. this._leafMemberCache = []; this._nonLeafMemberCache = []; }, /** * Returns the metadata column unique identifer * @return {String} The identifier used for metadata column expression */ getId: function getId() { return this.moserObject.getIdForExpression(); }, /** * Returns the metadata column label * @return {String} The metadata column display label */ getLabel: function getLabel() { return this.moserObject.getLabel(); }, /** * Set the metadata column label * @param {String} label The metadata column display label */ setLabel: function setLabel(label) { this.moserObject.setLabel(label); }, /** * Determines whether the metadata column is hidden * @return {Booelan} true if metadata column is hidden, otherwise false */ isHidden: function isHidden() { return this.moserObject.isHidden(); }, /** * Set the metadata column as hidden * @param {Booelan} isHidden true if metadata column is hidden, otherwise false */ setHidden: function setHidden(isHidden) { this.moserObject.setHidden(isHidden); }, /** * Returns the metadata column object type * @return {String} The metadata column object type */ getObjectType: function getObjectType() { return this.moserObject.getObjectType(); }, /** * Returns the internal spec ID of the source * @return {String} The internal id used to map a widget to the source it's using */ getSourceId: function getSourceId() { return this.sourceId; }, /** * Returns the internal spec ID of the source * @return {String} The internal id used to map a widget to the source it's using */ getFacetDefinition: function getFacetDefinition() { return this.moserObject.facetDefinition; }, // returns true if is WA2 style hierarchy, i.e. user generated hiearchy from UI. isItemHierarchy: function isItemHierarchy() { return this.moserObject.getObjectType() === MoserJS['default'].MoserObjectTypes.ITEM_HIERARCHY; }, // Returns true if metadata columns is missing in datasource. isMissing: function isMissing() { return this.moserObject.isMissing && this.moserObject.isMissing(); }, // returns true if is olap hierarchy. isHierarchy: function isHierarchy() { return this.getSourceCategory() === 'hierarchy/level' || this.getSourceCategory() === 'hierarchy/parent-child'; }, // returns true if isItemHierarchy or isHierarchy. hasMemberTree: function hasMemberTree() { return this.isItemHierarchy() || this.isHierarchy(); }, isSingleRootHierarchy: function isSingleRootHierarchy() { return !this.moserObject.isHierarchyHasMultipleRoots(); }, getRootMember: function getRootMember() { return this.moserObject.getRootMember(); }, // returns true if is olap level. isLevel: function isLevel() { return this.getSourceCategory() === 'level'; }, // returns true if is property. isProperty: function isProperty() { return this.getSourceCategory() === 'property'; }, // returns true if is namedSet. isNamedSet: function isNamedSet() { return this.getSourceCategory() === 'namedSet'; }, /** * Get the type of the column * @return {String} Returns eitehr 'fact' or 'attribute' as the column type. Null if the moserObject doesn't have a type */ getType: function getType() { if (!this.moserObject.getUsage) { return null; } if (this.moserObject.getUsage() === MoserJS['default'].UsageType.FACT) { return 'fact'; } else { return 'attribute'; } }, /** * @return the source category of the column, such as 'hierarchy', or 'level', etc, for relational type of dataset, this should return as 'column' **/ getSourceCategory: function getSourceCategory() { if (!this.isMissing() && this.moserObject.getSourceCategory && this.moserObject.getSourceCategory() !== null) { return this.moserObject.getSourceCategory().value(); } return null; }, /** * Returns the data type of the column * @return {[type]} [description] */ getDataType: function getDataType() { var dataType = void 0; // Should call getHighlevelDatatype for generic data types if (this.moserObject.getHighlevelDatatype) { var oHighLevelDataType = this.moserObject.getHighlevelDatatype(); dataType = oHighLevelDataType && oHighLevelDataType.value(); } if (!dataType || !dataType.toUpperCase /** if result is not a string */) { // If nothing provided from getHighlevelDatatype, follow the old logic to call getDatatype api dataType = this.moserObject.getDatatype ? this.moserObject.getDatatype() : null; } dataType = dataType ? dataType.toUpperCase() : null; if (dataType && DATA_TYPE_MAP[dataType]) { return DATA_TYPE_MAP[dataType]; } return this.getType() === 'fact' ? 'decimal' : 'string'; }, /** * @param optionalOverrideDataType - takes an optional datatype to check if it is a date or time, if null will use the Column dataType * @returns true if this item is a date, datetime, time or year. */ isDateOrTimeType: function isDateOrTimeType() { var dataType = this.getDataType(); return dataType === 'date' || dataType === 'datetime' || dataType === 'time' || dataType === 'year'; }, getConcepts: function getConcepts() { var concepts = this.moserObject.getConcepts ? this.moserObject.getConcepts() : null; if (concepts) { return concepts.slice(); } return null; }, getTaxonomy: function getTaxonomy() { var taxonomy = this.moserObject.basicGetTaxonomy ? this.moserObject.basicGetTaxonomy() : null; if (taxonomy && taxonomy.length > 0) { if (this.isSupportedTaxonomy(taxonomy[0])) { return taxonomy.slice(); } else { // Moser returns only 1 taxonomy element for each data item return null; } } return null; }, /** * Some columns, depending on their meta data should not allow search * or filter conditions to be set. For example, lat and long columns. * @returns if a metadata column should allow filter conditions and search. */ supportsConditionFilters: function supportsConditionFilters() { if (this.isNamedSet()) { return false; } var taxonomy = this.getTaxonomy(); var supported = true; if (taxonomy) { taxonomy.forEach(function (taxonomyItem) { var family = taxonomyItem.getFamily(); if (family === 'cLatitude' || family === 'cLongitude') { supported = false; } }); } return supported; }, // In R9, we support everything, except coordinates (family= cPosition) isSupportedTaxonomy: function isSupportedTaxonomy(taxonomy) { return taxonomy.getClazz() === 'cGeoLocation' && taxonomy.getFamily() === 'cPosition' ? false : true; }, getDefaultAggregation: function getDefaultAggregation() { if (!this._defaultAggregation) { var regularAggregate = this.moserObject.getRegularAggregate && this.moserObject.getRegularAggregate() ? this.moserObject.getRegularAggregate().value() : null; this._defaultAggregation = MetadataColumn.AGGREGATION_TYPE_MAP[regularAggregate] || UNKNOWN_AGGREGATE_TYPE; // Default to 'count' aggregation type for attribute that has unsupported aggregation types if (MetadataColumn.SUPPORTED_AGGREGATION_FOR_ATTRIBUTE.indexOf(this._defaultAggregation) === -1 && this.getType() === 'attribute') { this._defaultAggregation = MetadataColumn.AGGREGATION_TYPE_MAP.countDistinct; } } return this._defaultAggregation; }, getAggregateMode: function getAggregateMode() { if (this.moserObject.getAggregateMode) { var aggregateMode = this.moserObject.getAggregateMode(); return aggregateMode ? aggregateMode.value() : null; } return null; }, isFilter: function isFilter() { return this.moserObject.getObjectType() === MoserJS['default'].MoserObjectTypes.FILTER; }, /** * @description Return the data format for this metadata item. * @function MetadataColumn#getFormat * @public * * @param {Object} options ignoreDefaultFormatting - Ignore any default formatting * @return {FormatSpec} return format spec */ getFormat: function getFormat() { return FormatUtils.getFormatSpec(this.moserObject.getFormat && this.moserObject.getFormat()); }, /** * Returns the refToHierarchy of the moser object, e.g. refToHierarchy of a namedSet object * is the hierarchy the namedSet belongs to. * @return {string} hierarchy name. */ getRefToHierarchy: function getRefToHierarchy() { return this.moserObject.getRefToHierarchy ? this.moserObject.getRefToHierarchy() : null; }, /** * @param {Boolean} [isOlapPackage], Default False * @return {Boolean} True, if the column is regarded as a OLAP column */ isOlapColumn: function isOlapColumn() { var isOlapPackage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var sourceCategory = this.getSourceCategory(); // For datasource of Module that is built on top of OLAP packages, stand alone calculation or folder is not considered as OLAP column in this function. // For datasource of OLAP package directly, calcualtion is considered as OLAP column var isOlapCalculation = isOlapPackage && this.getObjectType() === 'Calculation'; return this.isNamedSet() || isOlapCalculation || sourceCategory && sourceCategory !== 'column' && this.getObjectType() === 'QueryItem'; }, getParent: function getParent() { var parent = this.moserObject.getParent(); while (parent && parent.getObjectType() === MoserJS['default'].MoserObjectTypes.ITEM_TYPE) { parent = parent.getParent(); } return parent ? new MetadataColumn({ moserObject: parent, sourceId: this.sourceId }) : null; }, isEditableCalculation: function isEditableCalculation() { return !this.moserObject.isImported() && (this.getObjectType() === MoserJS['default'].MoserObjectTypes.CALCULATION || this.getObjectType() === MoserJS['default'].MoserObjectTypes.QUERY_ITEM); }, getDefaultSortType: function getDefaultSortType() { var facetDefinition = this.moserObject.getFacetDefinition ? this.moserObject.getFacetDefinition() : null; if (!facetDefinition || !facetDefinition.enabled || facetDefinition.enabled && (facetDefinition.enabled.enumValue === 'false' || facetDefinition.enabled.enumValue === 'automatic')) { return null; } var sortList = facetDefinition.getSortList(); if (sortList) { var sortItems = sortList.basicGetSortItem(); if (sortItems && sortItems.length > 0) { // MUI doesn't allow to set many columns in sort list but Moser schema allows. // Take the order of the first sort item var sortItem = sortItems[0]; if (sortItem.order.enumValue === 'descending') { return SORT_DESCENDING; } else if (sortItem.order.enumValue === 'ascending') { return SORT_ASCENDING; } else { return null; } } } return null; }, /** * @return true if it's a leaf member by checking the cached leaf members. */ isCachedLeafMember: function isCachedLeafMember(mun) { return this._leafMemberCache.indexOf(mun) > -1; }, /** * @return true if it's not a leaf member by checking the cached non-leaf members. */ isCachedNonLeafMember: function isCachedNonLeafMember(mun) { return this._nonLeafMemberCache.indexOf(mun) > -1; }, cacheMember: function cacheMember(mun, isLeafMember) { if (isLeafMember) { this._leafMemberCache.push(mun); } else { this._nonLeafMemberCache.push(mun); } }, isLeafMember: function isLeafMember(memberId) { var _this = this; if (this.isCachedLeafMember(memberId)) { return Promise.resolve(true); } if (this.isCachedNonLeafMember(memberId)) { return Promise.resolve(false); } return this.queryService.getChildren(this.sourceId, [this.getId()], memberId, []).then(function (queryResult) { var isLeafMember = queryResult.getRowCount() === 0; _this.cacheMember(memberId, isLeafMember); return isLeafMember; }); }, getValues: function getValues() { return this.values; }, setValues: function setValues(values) { this.values = values; }, /** * Returns the table name where this metadata column is defined in * * @return {string} the retrieved table name */ getTableName: function getTableName() { var table = this.getTable(); return table ? table.getIdentifier() : ''; }, /** * Returns the table where this metadata column belong * * @return {object} return valid table object if one found else return undefined */ getTable: function getTable() { if (!this.table) { var parent = this.moserObject.getParent(); while (parent) { if (parent.getObjectType() === MoserJS.default.MoserObjectTypes.QUERY_SUBJECT) { this.table = parent; break; } parent = parent.getParent(); } } return this.table; }, isNumericDataType: function isNumericDataType() { var type = this.getDataType(); return ['string', 'attribute', 'date', 'time', 'datetime'].indexOf(type) === -1; }, isDateTimeDataType: function isDateTimeDataType() { var type = this.getDataType(); return ['date', 'time', 'datetime'].indexOf(type) !== -1; }, /* * @return {string array} an array of properties that had been overriden */ getPropertyOverride: function getPropertyOverride() { return this.moserObject.getPropertyOverride().filter(function (property) { return property.indexOf('property') === -1; }).map(function (property) { return { property: property, value: this.getProperty(property) }; }.bind(this)); }, getProperty: function getProperty(propertyName) { if (this.moserObject[propertyName] && this.moserObject[propertyName].value) { return this.moserObject[propertyName].value(); } return this.moserObject[propertyName]; }, getMoserObject: function getMoserObject() { return this.moserObject; }, /** * Compatible with MetadataColumnAPI#getHierarchyLevelIds * @description Returns the levelIds of the hierarchy in natural order. * * @return {String[]} an array of levelIds */ getHierarchyLevelIds: function getHierarchyLevelIds() { return this.moserObject.getItem().filter(function (item) { return item.queryItem; }).map(function (item) { return item.queryItem.getIdForExpression(); }) || []; } }); MetadataColumn.AGGREGATION_TYPE_MAP = { none: 'none', average: 'avg', automatic: 'automatic', calculated: 'calculated', count: 'count', countDistinct: 'countdistinct', maximum: 'max', median: 'median', minimum: 'min', standardDeviation: 'stddev', total: 'sum', variance: 'variance' }; // Currently we only support none, count and countdistinct MetadataColumn.SUPPORTED_AGGREGATION_FOR_ATTRIBUTE = [MetadataColumn.AGGREGATION_TYPE_MAP.none, MetadataColumn.AGGREGATION_TYPE_MAP.count, MetadataColumn.AGGREGATION_TYPE_MAP.countDistinct]; //The set of aggregation types that are valid for fact type columns MetadataColumn.SUPPORTED_AGGREGATION_FOR_FACT = [MetadataColumn.AGGREGATION_TYPE_MAP.average, MetadataColumn.AGGREGATION_TYPE_MAP.total, MetadataColumn.AGGREGATION_TYPE_MAP.minimum, MetadataColumn.AGGREGATION_TYPE_MAP.maximum, MetadataColumn.AGGREGATION_TYPE_MAP.count, MetadataColumn.AGGREGATION_TYPE_MAP.countDistinct]; return MetadataColumn; }); //# sourceMappingURL=MetadataColumn.js.map