/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * AUTO-GENERATED FILE. DO NOT MODIFY. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import { VISUAL_DIMENSIONS } from '../../util/types.js'; import SeriesDimensionDefine from '../SeriesDimensionDefine.js'; import { createHashMap, defaults, each, extend, isObject, isString } from 'zrender/lib/core/util.js'; import { createSourceFromSeriesDataOption, isSourceInstance } from '../Source.js'; import { CtorInt32Array } from '../DataStore.js'; import { normalizeToArray } from '../../util/model.js'; import { BE_ORDINAL, guessOrdinal } from './sourceHelper.js'; import { createDimNameMap, ensureSourceDimNameMap, SeriesDataSchema, shouldOmitUnusedDimensions } from './SeriesDataSchema.js'; /** * For outside usage compat (like echarts-gl are using it). */ export function createDimensions(source, opt) { return prepareSeriesDataSchema(source, opt).dimensions; } /** * This method builds the relationship between: * + "what the coord sys or series requires (see `coordDimensions`)", * + "what the user defines (in `encode` and `dimensions`, see `opt.dimensionsDefine` and `opt.encodeDefine`)" * + "what the data source provids (see `source`)". * * Some guess strategy will be adapted if user does not define something. * If no 'value' dimension specified, the first no-named dimension will be * named as 'value'. * * @return The results are always sorted by `storeDimIndex` asc. */ export default function prepareSeriesDataSchema( // TODO: TYPE completeDimensions type source, opt) { if (!isSourceInstance(source)) { source = createSourceFromSeriesDataOption(source); } opt = opt || {}; var sysDims = opt.coordDimensions || []; var dimsDef = opt.dimensionsDefine || source.dimensionsDefine || []; var coordDimNameMap = createHashMap(); var resultList = []; var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimensionsCount); // Try to ignore unused dimensions if sharing a high dimension datastore // 30 is an experience value. var omitUnusedDimensions = opt.canOmitUnusedDimensions && shouldOmitUnusedDimensions(dimCount); var isUsingSourceDimensionsDef = dimsDef === source.dimensionsDefine; var dataDimNameMap = isUsingSourceDimensionsDef ? ensureSourceDimNameMap(source) : createDimNameMap(dimsDef); var encodeDef = opt.encodeDefine; if (!encodeDef && opt.encodeDefaulter) { encodeDef = opt.encodeDefaulter(source, dimCount); } var encodeDefMap = createHashMap(encodeDef); var indicesMap = new CtorInt32Array(dimCount); for (var i = 0; i < indicesMap.length; i++) { indicesMap[i] = -1; } function getResultItem(dimIdx) { var idx = indicesMap[dimIdx]; if (idx < 0) { var dimDefItemRaw = dimsDef[dimIdx]; var dimDefItem = isObject(dimDefItemRaw) ? dimDefItemRaw : { name: dimDefItemRaw }; var resultItem = new SeriesDimensionDefine(); var userDimName = dimDefItem.name; if (userDimName != null && dataDimNameMap.get(userDimName) != null) { // Only if `series.dimensions` is defined in option // displayName, will be set, and dimension will be displayed vertically in // tooltip by default. resultItem.name = resultItem.displayName = userDimName; } dimDefItem.type != null && (resultItem.type = dimDefItem.type); dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); var newIdx = resultList.length; indicesMap[dimIdx] = newIdx; resultItem.storeDimIndex = dimIdx; resultList.push(resultItem); return resultItem; } return resultList[idx]; } if (!omitUnusedDimensions) { for (var i = 0; i < dimCount; i++) { getResultItem(i); } } // Set `coordDim` and `coordDimIndex` by `encodeDefMap` and normalize `encodeDefMap`. encodeDefMap.each(function (dataDimsRaw, coordDim) { var dataDims = normalizeToArray(dataDimsRaw).slice(); // Note: It is allowed that `dataDims.length` is `0`, e.g., options is // `{encode: {x: -1, y: 1}}`. Should not filter anything in // this case. if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) { encodeDefMap.set(coordDim, false); return; } var validDataDims = encodeDefMap.set(coordDim, []); each(dataDims, function (resultDimIdxOrName, idx) { // The input resultDimIdx can be dim name or index. var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName; if (resultDimIdx != null && resultDimIdx < dimCount) { validDataDims[idx] = resultDimIdx; applyDim(getResultItem(resultDimIdx), coordDim, idx); } }); }); // Apply templates and default order from `sysDims`. var availDimIdx = 0; each(sysDims, function (sysDimItemRaw) { var coordDim; var sysDimItemDimsDef; var sysDimItemOtherDims; var sysDimItem; if (isString(sysDimItemRaw)) { coordDim = sysDimItemRaw; sysDimItem = {}; } else { sysDimItem = sysDimItemRaw; coordDim = sysDimItem.name; var ordinalMeta = sysDimItem.ordinalMeta; sysDimItem.ordinalMeta = null; sysDimItem = extend({}, sysDimItem); sysDimItem.ordinalMeta = ordinalMeta; // `coordDimIndex` should not be set directly. sysDimItemDimsDef = sysDimItem.dimsDef; sysDimItemOtherDims = sysDimItem.otherDims; sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null; } var dataDims = encodeDefMap.get(coordDim); // negative resultDimIdx means no need to mapping. if (dataDims === false) { return; } dataDims = normalizeToArray(dataDims); // dimensions provides default dim sequences. if (!dataDims.length) { for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { while (availDimIdx < dimCount && getResultItem(availDimIdx).coordDim != null) { availDimIdx++; } availDimIdx < dimCount && dataDims.push(availDimIdx++); } } // Apply templates. each(dataDims, function (resultDimIdx, coordDimIndex) { var resultItem = getResultItem(resultDimIdx); // Coordinate system has a higher priority on dim type than source. if (isUsingSourceDimensionsDef && sysDimItem.type != null) { resultItem.type = sysDimItem.type; } applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); if (resultItem.name == null && sysDimItemDimsDef) { var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex]; !isObject(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = { name: sysDimItemDimsDefItem }); resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name; resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip; } // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}} sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); }); }); function applyDim(resultItem, coordDim, coordDimIndex) { if (VISUAL_DIMENSIONS.get(coordDim) != null) { resultItem.otherDims[coordDim] = coordDimIndex; } else { resultItem.coordDim = coordDim; resultItem.coordDimIndex = coordDimIndex; coordDimNameMap.set(coordDim, true); } } // Make sure the first extra dim is 'value'. var generateCoord = opt.generateCoord; var generateCoordCount = opt.generateCoordCount; var fromZero = generateCoordCount != null; generateCoordCount = generateCoord ? generateCoordCount || 1 : 0; var extra = generateCoord || 'value'; function ifNoNameFillWithCoordName(resultItem) { if (resultItem.name == null) { // Duplication will be removed in the next step. resultItem.name = resultItem.coordDim; } } // Set dim `name` and other `coordDim` and other props. if (!omitUnusedDimensions) { for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { var resultItem = getResultItem(resultDimIdx); var coordDim = resultItem.coordDim; if (coordDim == null) { // TODO no need to generate coordDim for isExtraCoord? resultItem.coordDim = genCoordDimName(extra, coordDimNameMap, fromZero); resultItem.coordDimIndex = 0; // Series specified generateCoord is using out. if (!generateCoord || generateCoordCount <= 0) { resultItem.isExtraCoord = true; } generateCoordCount--; } ifNoNameFillWithCoordName(resultItem); if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must // Consider the case: // { // dataset: {source: [ // ['2001', 123], // ['2002', 456], // ... // ['The others', 987], // ]}, // series: {type: 'pie'} // } // The first column should better be treated as a "ordinal" although it // might not be detected as an "ordinal" by `guessOrdinal`. || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) { resultItem.type = 'ordinal'; } } } else { each(resultList, function (resultItem) { // PENDING: guessOrdinal or let user specify type: 'ordinal' manually? ifNoNameFillWithCoordName(resultItem); }); // Sort dimensions: there are some rule that use the last dim as label, // and for some latter travel process easier. resultList.sort(function (item0, item1) { return item0.storeDimIndex - item1.storeDimIndex; }); } removeDuplication(resultList); return new SeriesDataSchema({ source: source, dimensions: resultList, fullDimensionCount: dimCount, dimensionOmitted: omitUnusedDimensions }); } function removeDuplication(result) { var duplicationMap = createHashMap(); for (var i = 0; i < result.length; i++) { var dim = result[i]; var dimOriginalName = dim.name; var count = duplicationMap.get(dimOriginalName) || 0; if (count > 0) { // Starts from 0. dim.name = dimOriginalName + (count - 1); } count++; duplicationMap.set(dimOriginalName, count); } } // ??? TODO // Originally detect dimCount by data[0]. Should we // optimize it to only by sysDims and dimensions and encode. // So only necessary dims will be initialized. // But // (1) custom series should be considered. where other dims // may be visited. // (2) sometimes user need to calculate bubble size or use visualMap // on other dimensions besides coordSys needed. // So, dims that is not used by system, should be shared in data store? function getDimCount(source, sysDims, dimsDef, optDimCount) { // Note that the result dimCount should not small than columns count // of data, otherwise `dataDimNameMap` checking will be incorrect. var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0); each(sysDims, function (sysDimItem) { var sysDimItemDimsDef; if (isObject(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) { dimCount = Math.max(dimCount, sysDimItemDimsDef.length); } }); return dimCount; } function genCoordDimName(name, map, fromZero) { if (fromZero || map.hasKey(name)) { var i = 0; while (map.hasKey(name + i)) { i++; } name += i; } map.set(name, true); return name; }