| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- /**
- * DevExtreme (viz/components/data_validator.js)
- * Version: 19.1.16
- * Build date: Tue Oct 18 2022
- *
- * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
- * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
- */
- "use strict";
- var typeUtils = require("../../core/utils/type");
- var STRING = "string";
- var NUMERIC = "numeric";
- var DATETIME = "datetime";
- var DISCRETE = "discrete";
- var SEMIDISCRETE = "semidiscrete";
- var CONTINUOUS = "continuous";
- var LOGARITHMIC = "logarithmic";
- var VALUE_TYPE = "valueType";
- var ARGUMENT_TYPE = "argumentType";
- var extend = require("../../core/utils/extend").extend;
- var axisTypeParser = require("../core/utils").enumParser([STRING, NUMERIC, DATETIME]);
- var _getParser = require("./parse_utils").getParser;
- var _isDefined = typeUtils.isDefined;
- var _isFunction = typeUtils.isFunction;
- var _isArray = Array.isArray;
- var _isString = typeUtils.isString;
- var _isDate = typeUtils.isDate;
- var _isNumber = typeUtils.isNumeric;
- var _isObject = typeUtils.isObject;
- function groupingValues(data, others, valueField, index) {
- if (index >= 0) {
- data.slice(index).forEach(function(cell) {
- if (_isDefined(cell[valueField])) {
- others[valueField] += cell[valueField];
- cell[valueField] = void 0
- }
- })
- }
- }
- function processGroups(groups) {
- groups.forEach(function(group) {
- group.valueType = group.valueAxisType = null;
- group.series.forEach(function(series) {
- series.updateDataType({})
- });
- group.valueAxis && group.valueAxis.resetTypes(VALUE_TYPE)
- })
- }
- function sortValues(data, asc, selector) {
- var func = asc ? function(a, b) {
- return a - b
- } : function(a, b) {
- return b - a
- };
- data.sort(function(a, b) {
- var valA = selector(a);
- var valB = selector(b);
- var aa = _isDefined(valA) ? 1 : 0;
- var bb = _isDefined(valB) ? 1 : 0;
- return aa && bb ? func(valA, valB) : func(aa, bb)
- });
- return data
- }
- function resetArgumentAxes(axes) {
- axes && axes.forEach(function(axis) {
- axis.resetTypes(ARGUMENT_TYPE)
- })
- }
- function parseCategories(categories, parser) {
- var newArray = [];
- categories.forEach(function(category) {
- var parsedCategory = parser(category);
- void 0 !== parsedCategory && newArray.push(parsedCategory)
- });
- return newArray
- }
- function parseAxisCategories(groupsData, parsers) {
- var argumentCategories = groupsData.argumentOptions && groupsData.argumentOptions.categories;
- groupsData.groups.forEach(function(valueGroup, i) {
- var categories = valueGroup.valueOptions && valueGroup.valueOptions.categories;
- if (categories) {
- valueGroup.valueOptions.categories = parseCategories(categories, parsers[i + 1])
- }
- });
- if (argumentCategories) {
- groupsData.argumentOptions.categories = parseCategories(argumentCategories, parsers[0])
- }
- }
- function filterForLogAxis(val, field, incidentOccurred) {
- if (val <= 0 && null !== val) {
- incidentOccurred("E2004", [field]);
- val = null
- }
- return val
- }
- function eigen(x) {
- return x
- }
- function getType(unit, type) {
- var result = type;
- if (type === STRING || _isString(unit)) {
- result = STRING
- } else {
- if (type === DATETIME || _isDate(unit)) {
- result = DATETIME
- } else {
- if (_isNumber(unit)) {
- result = NUMERIC
- }
- }
- }
- return result
- }
- function correctAxisType(type, axisType, hasCategories, incidentOccurred) {
- if (type === STRING && (axisType === CONTINUOUS || axisType === LOGARITHMIC || axisType === SEMIDISCRETE)) {
- incidentOccurred("E2002")
- }
- return axisType === LOGARITHMIC ? LOGARITHMIC : hasCategories || axisType === DISCRETE || type === STRING ? DISCRETE : axisType === SEMIDISCRETE ? SEMIDISCRETE : CONTINUOUS
- }
- function validUnit(unit, field, incidentOccurred) {
- if (unit) {
- incidentOccurred(!_isNumber(unit) && !_isDate(unit) && !_isString(unit) ? "E2003" : "E2004", [field])
- }
- }
- function createParserUnit(type, axisType, incidentOccurred) {
- var parser = type ? _getParser(type) : eigen;
- var filter = axisType === LOGARITHMIC ? filterForLogAxis : eigen;
- var filterInfinity = axisType !== DISCRETE ? function(x) {
- return isFinite(x) || void 0 === x ? x : null
- } : eigen;
- return function(unit, field) {
- var filterLogValues = function(x) {
- return filter(x, field, incidentOccurred)
- };
- var parseUnit = filterLogValues(filterInfinity(parser(unit)));
- if (void 0 === parseUnit) {
- validUnit(unit, field, incidentOccurred)
- }
- return parseUnit
- }
- }
- function prepareParsers(groupsData, incidentOccurred) {
- var argumentParser = createParserUnit(groupsData.argumentType, groupsData.argumentAxisType, incidentOccurred);
- var sizeParser;
- var valueParser;
- var categoryParsers = [argumentParser];
- var cache = {};
- var list = [];
- groupsData.groups.forEach(function(group, groupIndex) {
- group.series.forEach(function(series) {
- valueParser = createParserUnit(group.valueType, group.valueAxisType, incidentOccurred);
- sizeParser = createParserUnit(NUMERIC, CONTINUOUS, incidentOccurred);
- cache[series.getArgumentField()] = argumentParser;
- series.getValueFields().forEach(function(field) {
- categoryParsers[groupIndex + 1] = valueParser;
- cache[field] = valueParser
- });
- if (series.getSizeField()) {
- cache[series.getSizeField()] = sizeParser
- }
- })
- });
- for (var field in cache) {
- list.push([field, cache[field]])
- }
- list.length && parseAxisCategories(groupsData, categoryParsers);
- return list
- }
- function getParsedCell(cell, parsers) {
- var i;
- var ii = parsers.length;
- var obj = extend({}, cell);
- var field;
- var value;
- for (i = 0; i < ii; ++i) {
- field = parsers[i][0];
- value = cell[field];
- obj[field] = parsers[i][1](value, field)
- }
- return obj
- }
- function parse(data, parsers) {
- var parsedData = [];
- var i;
- var ii = data.length;
- parsedData.length = ii;
- for (i = 0; i < ii; ++i) {
- parsedData[i] = getParsedCell(data[i], parsers)
- }
- return parsedData
- }
- function findIndexByThreshold(data, valueField, threshold) {
- var i;
- var ii = data.length;
- var value;
- for (i = 0; i < ii; ++i) {
- value = data[i][valueField];
- if (_isDefined(value) && threshold > value) {
- break
- }
- }
- return i
- }
- function groupMinSlices(originalData, argumentField, valueField, smallValuesGrouping) {
- smallValuesGrouping = smallValuesGrouping || {};
- var mode = smallValuesGrouping.mode;
- var others = {};
- if (!mode || "none" === mode) {
- return
- }
- others[argumentField] = String(smallValuesGrouping.groupName || "others");
- others[valueField] = 0;
- var data = sortValues(originalData.slice(), false, function(a) {
- return a[valueField]
- });
- groupingValues(data, others, valueField, "smallValueThreshold" === mode ? findIndexByThreshold(data, valueField, smallValuesGrouping.threshold) : smallValuesGrouping.topCount);
- others[valueField] && originalData.push(others)
- }
- function groupPieData(data, groupsData) {
- var firstSeries = groupsData.groups[0] && groupsData.groups[0].series[0];
- var isPie = firstSeries && ("pie" === firstSeries.type || "doughnut" === firstSeries.type || "donut" === firstSeries.type);
- if (!isPie) {
- return
- }
- groupsData.groups.forEach(function(group) {
- group.series.forEach(function(series) {
- groupMinSlices(data, series.getArgumentField(), series.getValueFields()[0], series.getOptions().smallValuesGrouping)
- })
- })
- }
- function addUniqueItemToCollection(item, collection, itemsHash) {
- if (!itemsHash[item]) {
- collection.push(item);
- itemsHash[item] = true
- }
- }
- function getUniqueArgumentFields(groupsData) {
- var uniqueArgumentFields = [];
- var hash = {};
- groupsData.groups.forEach(function(group) {
- group.series.forEach(function(series) {
- addUniqueItemToCollection(series.getArgumentField(), uniqueArgumentFields, hash)
- })
- });
- return uniqueArgumentFields
- }
- function sort(a, b) {
- var result = a - b;
- if (isNaN(result)) {
- if (!_isDefined(a)) {
- return 1
- }
- if (!_isDefined(b)) {
- return -1
- }
- return 0
- }
- return result
- }
- function sortByArgument(data, argumentField) {
- return data.slice().sort(function(a, b) {
- return sort(a[argumentField], b[argumentField])
- })
- }
- function sortByCallback(data, callback) {
- return data.slice().sort(callback)
- }
- function checkValueTypeOfGroup(group, cell) {
- group.series.forEach(function(series) {
- series.getValueFields().forEach(function(field) {
- group.valueType = getType(cell[field], group.valueType)
- })
- });
- return group.valueType
- }
- function getSortByCategories(categories) {
- var hash = {};
- categories.forEach(function(value, i) {
- hash[value] = i
- });
- return function(data, argumentField) {
- return sortValues(data.slice(), true, function(a) {
- return hash[a[argumentField]]
- })
- }
- }
- function sortData(data, groupsData, options, uniqueArgumentFields) {
- var dataByArguments = {};
- var isDiscrete = groupsData.argumentAxisType === DISCRETE;
- var userCategories = isDiscrete && groupsData.argumentOptions && groupsData.argumentOptions.categories;
- var sortFunction = function(data) {
- return data
- };
- var sortingMethodOption = options.sortingMethod;
- var reSortCategories;
- if (!userCategories && _isFunction(sortingMethodOption)) {
- data = sortByCallback(data, sortingMethodOption)
- }
- if (isDiscrete) {
- groupsData.categories = getCategories(data, uniqueArgumentFields, userCategories)
- }
- if (userCategories || !_isFunction(sortingMethodOption) && groupsData.argumentType === STRING && !options._skipArgumentSorting) {
- sortFunction = getSortByCategories(groupsData.categories)
- } else {
- if (true === sortingMethodOption && groupsData.argumentType !== STRING) {
- sortFunction = sortByArgument;
- reSortCategories = isDiscrete
- }
- }
- uniqueArgumentFields.forEach(function(field) {
- dataByArguments[field] = sortFunction(data, field)
- });
- if (reSortCategories) {
- groupsData.categories = groupsData.categories.sort(sort)
- }
- return dataByArguments
- }
- function checkItemExistence(collection, item) {
- return collection.map(function(collectionItem) {
- return collectionItem.valueOf()
- }).indexOf(item.valueOf()) === -1
- }
- function getCategories(data, uniqueArgumentFields, userCategories) {
- var categories = userCategories ? userCategories.slice() : [];
- uniqueArgumentFields.forEach(function(field) {
- data.forEach(function(item) {
- var dataItem = item[field];
- _isDefined(dataItem) && checkItemExistence(categories, dataItem) && categories.push(dataItem)
- })
- });
- return categories
- }
- function checkArgumentTypeOfGroup(series, cell, groupsData) {
- series.forEach(function(currentSeries) {
- groupsData.argumentType = getType(cell[currentSeries.getArgumentField()], groupsData.argumentType)
- });
- return groupsData.argumentType
- }
- function checkType(data, groupsData, checkTypeForAllData) {
- var groupsWithUndefinedValueType = [];
- var groupsWithUndefinedArgumentType = [];
- var argumentTypeGroup = groupsData.argumentOptions && axisTypeParser(groupsData.argumentOptions.argumentType);
- var groupsIndexes;
- groupsData.groups.forEach(function(group) {
- if (!group.series.length) {
- return
- }
- var valueTypeGroup = group.valueOptions && axisTypeParser(group.valueOptions.valueType);
- group.valueType = valueTypeGroup;
- groupsData.argumentType = argumentTypeGroup;
- !valueTypeGroup && groupsWithUndefinedValueType.push(group);
- !argumentTypeGroup && groupsWithUndefinedArgumentType.push(group)
- });
- if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length) {
- groupsIndexes = groupsWithUndefinedValueType.map(function(_, index) {
- return index
- });
- data.some(function(cell) {
- var defineArg;
- groupsWithUndefinedValueType.forEach(function(group, groupIndex) {
- if (checkValueTypeOfGroup(group, cell) && groupsIndexes.indexOf(groupIndex) >= 0) {
- groupsIndexes.splice(groupIndex, 1)
- }
- });
- if (!defineArg) {
- groupsWithUndefinedArgumentType.forEach(function(group) {
- defineArg = checkArgumentTypeOfGroup(group.series, cell, groupsData)
- })
- }
- if (!checkTypeForAllData && defineArg && 0 === groupsIndexes.length) {
- return true
- }
- })
- }
- }
- function checkAxisType(groupsData, incidentOccurred) {
- var argumentOptions = groupsData.argumentOptions || {};
- var userArgumentCategories = argumentOptions && argumentOptions.categories || [];
- var argumentAxisType = correctAxisType(groupsData.argumentType, argumentOptions.type, !!userArgumentCategories.length, incidentOccurred);
- groupsData.groups.forEach(function(group) {
- var valueOptions = group.valueOptions || {};
- var valueCategories = valueOptions.categories || [];
- var valueAxisType = correctAxisType(group.valueType, valueOptions.type, !!valueCategories.length, incidentOccurred);
- group.series.forEach(function(series) {
- var optionsSeries = {};
- optionsSeries.argumentAxisType = argumentAxisType;
- optionsSeries.valueAxisType = valueAxisType;
- groupsData.argumentAxisType = groupsData.argumentAxisType || optionsSeries.argumentAxisType;
- group.valueAxisType = group.valueAxisType || optionsSeries.valueAxisType;
- optionsSeries.argumentType = groupsData.argumentType;
- optionsSeries.valueType = group.valueType;
- optionsSeries.showZero = valueOptions.showZero;
- series.updateDataType(optionsSeries)
- });
- group.valueAxisType = group.valueAxisType || valueAxisType;
- if (group.valueAxis) {
- group.valueAxis.setTypes(group.valueAxisType, group.valueType, VALUE_TYPE);
- group.valueAxis.validate()
- }
- });
- groupsData.argumentAxisType = groupsData.argumentAxisType || argumentAxisType;
- if (groupsData.argumentAxes) {
- groupsData.argumentAxes.forEach(function(axis) {
- axis.setTypes(groupsData.argumentAxisType, groupsData.argumentType, ARGUMENT_TYPE);
- axis.validate()
- })
- }
- }
- function verifyData(source, incidentOccurred) {
- var data = [];
- var sourceIsDefined = _isDefined(source);
- var hasError = sourceIsDefined && !_isArray(source);
- var i;
- var ii;
- var k;
- var item;
- if (sourceIsDefined && !hasError) {
- for (i = 0, ii = source.length, k = 0; i < ii; ++i) {
- item = source[i];
- if (_isObject(item)) {
- data[k++] = item
- } else {
- if (item) {
- hasError = true
- }
- }
- }
- }
- if (hasError) {
- incidentOccurred("E2001")
- }
- return data
- }
- function validateData(data, groupsData, incidentOccurred, options) {
- data = verifyData(data, incidentOccurred);
- groupsData.argumentType = groupsData.argumentAxisType = null;
- processGroups(groupsData.groups);
- resetArgumentAxes(groupsData.argumentAxes);
- checkType(data, groupsData, options.checkTypeForAllData);
- checkAxisType(groupsData, incidentOccurred);
- if (options.convertToAxisDataType) {
- data = parse(data, prepareParsers(groupsData, incidentOccurred))
- }
- groupPieData(data, groupsData);
- var dataByArgumentFields = sortData(data, groupsData, options, getUniqueArgumentFields(groupsData));
- return dataByArgumentFields
- }
- exports.validateData = validateData;
|