|   | 
| /* | 
| * 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; | 
| } |