| 
/* 
 | 
* 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 { setAsPrimitive, map, isTypedArray, assert, each, retrieve2 } from 'zrender/lib/core/util.js'; 
 | 
import { createSource, cloneSourceShallow } from '../Source.js'; 
 | 
import { SOURCE_FORMAT_TYPED_ARRAY, SOURCE_FORMAT_ORIGINAL } from '../../util/types.js'; 
 | 
import { querySeriesUpstreamDatasetModel, queryDatasetUpstreamDatasetModels } from './sourceHelper.js'; 
 | 
import { applyDataTransform } from './transform.js'; 
 | 
import DataStore from '../DataStore.js'; 
 | 
import { DefaultDataProvider } from './dataProvider.js'; 
 | 
/** 
 | 
 * [REQUIREMENT_MEMO]: 
 | 
 * (0) `metaRawOption` means `dimensions`/`sourceHeader`/`seriesLayoutBy` in raw option. 
 | 
 * (1) Keep support the feature: `metaRawOption` can be specified both on `series` and 
 | 
 * `root-dataset`. Them on `series` has higher priority. 
 | 
 * (2) Do not support to set `metaRawOption` on a `non-root-dataset`, because it might 
 | 
 * confuse users: whether those props indicate how to visit the upstream source or visit 
 | 
 * the transform result source, and some transforms has nothing to do with these props, 
 | 
 * and some transforms might have multiple upstream. 
 | 
 * (3) Transforms should specify `metaRawOption` in each output, just like they can be 
 | 
 * declared in `root-dataset`. 
 | 
 * (4) At present only support visit source in `SERIES_LAYOUT_BY_COLUMN` in transforms. 
 | 
 * That is for reducing complexity in transforms. 
 | 
 * PENDING: Whether to provide transposition transform? 
 | 
 * 
 | 
 * [IMPLEMENTAION_MEMO]: 
 | 
 * "sourceVisitConfig" are calculated from `metaRawOption` and `data`. 
 | 
 * They will not be calculated until `source` is about to be visited (to prevent from 
 | 
 * duplicate calcuation). `source` is visited only in series and input to transforms. 
 | 
 * 
 | 
 * [DIMENSION_INHERIT_RULE]: 
 | 
 * By default the dimensions are inherited from ancestors, unless a transform return 
 | 
 * a new dimensions definition. 
 | 
 * Consider the case: 
 | 
 * ```js 
 | 
 * dataset: [{ 
 | 
 *     source: [ ['Product', 'Sales', 'Prise'], ['Cookies', 321, 44.21], ...] 
 | 
 * }, { 
 | 
 *     transform: { type: 'filter', ... } 
 | 
 * }] 
 | 
 * dataset: [{ 
 | 
 *     dimension: ['Product', 'Sales', 'Prise'], 
 | 
 *     source: [ ['Cookies', 321, 44.21], ...] 
 | 
 * }, { 
 | 
 *     transform: { type: 'filter', ... } 
 | 
 * }] 
 | 
 * ``` 
 | 
 * The two types of option should have the same behavior after transform. 
 | 
 * 
 | 
 * 
 | 
 * [SCENARIO]: 
 | 
 * (1) Provide source data directly: 
 | 
 * ```js 
 | 
 * series: { 
 | 
 *     encode: {...}, 
 | 
 *     dimensions: [...] 
 | 
 *     seriesLayoutBy: 'row', 
 | 
 *     data: [[...]] 
 | 
 * } 
 | 
 * ``` 
 | 
 * (2) Series refer to dataset. 
 | 
 * ```js 
 | 
 * series: [{ 
 | 
 *     encode: {...} 
 | 
 *     // Ignore datasetIndex means `datasetIndex: 0` 
 | 
 *     // and the dimensions defination in dataset is used 
 | 
 * }, { 
 | 
 *     encode: {...}, 
 | 
 *     seriesLayoutBy: 'column', 
 | 
 *     datasetIndex: 1 
 | 
 * }] 
 | 
 * ``` 
 | 
 * (3) dataset transform 
 | 
 * ```js 
 | 
 * dataset: [{ 
 | 
 *     source: [...] 
 | 
 * }, { 
 | 
 *     source: [...] 
 | 
 * }, { 
 | 
 *     // By default from 0. 
 | 
 *     transform: { type: 'filter', config: {...} } 
 | 
 * }, { 
 | 
 *     // Piped. 
 | 
 *     transform: [ 
 | 
 *         { type: 'filter', config: {...} }, 
 | 
 *         { type: 'sort', config: {...} } 
 | 
 *     ] 
 | 
 * }, { 
 | 
 *     id: 'regressionData', 
 | 
 *     fromDatasetIndex: 1, 
 | 
 *     // Third-party transform 
 | 
 *     transform: { type: 'ecStat:regression', config: {...} } 
 | 
 * }, { 
 | 
 *     // retrieve the extra result. 
 | 
 *     id: 'regressionFormula', 
 | 
 *     fromDatasetId: 'regressionData', 
 | 
 *     fromTransformResult: 1 
 | 
 * }] 
 | 
 * ``` 
 | 
 */ 
 | 
var SourceManager = /** @class */function () { 
 | 
  function SourceManager(sourceHost) { 
 | 
    // Cached source. Do not repeat calculating if not dirty. 
 | 
    this._sourceList = []; 
 | 
    this._storeList = []; 
 | 
    // version sign of each upstream source manager. 
 | 
    this._upstreamSignList = []; 
 | 
    this._versionSignBase = 0; 
 | 
    this._dirty = true; 
 | 
    this._sourceHost = sourceHost; 
 | 
  } 
 | 
  /** 
 | 
   * Mark dirty. 
 | 
   */ 
 | 
  SourceManager.prototype.dirty = function () { 
 | 
    this._setLocalSource([], []); 
 | 
    this._storeList = []; 
 | 
    this._dirty = true; 
 | 
  }; 
 | 
  SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) { 
 | 
    this._sourceList = sourceList; 
 | 
    this._upstreamSignList = upstreamSignList; 
 | 
    this._versionSignBase++; 
 | 
    if (this._versionSignBase > 9e10) { 
 | 
      this._versionSignBase = 0; 
 | 
    } 
 | 
  }; 
 | 
  /** 
 | 
   * For detecting whether the upstream source is dirty, so that 
 | 
   * the local cached source (in `_sourceList`) should be discarded. 
 | 
   */ 
 | 
  SourceManager.prototype._getVersionSign = function () { 
 | 
    return this._sourceHost.uid + '_' + this._versionSignBase; 
 | 
  }; 
 | 
  /** 
 | 
   * Always return a source instance. Otherwise throw error. 
 | 
   */ 
 | 
  SourceManager.prototype.prepareSource = function () { 
 | 
    // For the case that call `setOption` multiple time but no data changed, 
 | 
    // cache the result source to prevent from repeating transform. 
 | 
    if (this._isDirty()) { 
 | 
      this._createSource(); 
 | 
      this._dirty = false; 
 | 
    } 
 | 
  }; 
 | 
  SourceManager.prototype._createSource = function () { 
 | 
    this._setLocalSource([], []); 
 | 
    var sourceHost = this._sourceHost; 
 | 
    var upSourceMgrList = this._getUpstreamSourceManagers(); 
 | 
    var hasUpstream = !!upSourceMgrList.length; 
 | 
    var resultSourceList; 
 | 
    var upstreamSignList; 
 | 
    if (isSeries(sourceHost)) { 
 | 
      var seriesModel = sourceHost; 
 | 
      var data = void 0; 
 | 
      var sourceFormat = void 0; 
 | 
      var upSource = void 0; 
 | 
      // Has upstream dataset 
 | 
      if (hasUpstream) { 
 | 
        var upSourceMgr = upSourceMgrList[0]; 
 | 
        upSourceMgr.prepareSource(); 
 | 
        upSource = upSourceMgr.getSource(); 
 | 
        data = upSource.data; 
 | 
        sourceFormat = upSource.sourceFormat; 
 | 
        upstreamSignList = [upSourceMgr._getVersionSign()]; 
 | 
      } 
 | 
      // Series data is from own. 
 | 
      else { 
 | 
        data = seriesModel.get('data', true); 
 | 
        sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL; 
 | 
        upstreamSignList = []; 
 | 
      } 
 | 
      // See [REQUIREMENT_MEMO], merge settings on series and parent dataset if it is root. 
 | 
      var newMetaRawOption = this._getSourceMetaRawOption() || {}; 
 | 
      var upMetaRawOption = upSource && upSource.metaRawOption || {}; 
 | 
      var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption.seriesLayoutBy) || null; 
 | 
      var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption.sourceHeader); 
 | 
      // Note here we should not use `upSource.dimensionsDefine`. Consider the case: 
 | 
      // `upSource.dimensionsDefine` is detected by `seriesLayoutBy: 'column'`, 
 | 
      // but series need `seriesLayoutBy: 'row'`. 
 | 
      var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption.dimensions); 
 | 
      // We share source with dataset as much as possible 
 | 
      // to avoid extra memory cost of high dimensional data. 
 | 
      var needsCreateSource = seriesLayoutBy !== upMetaRawOption.seriesLayoutBy || !!sourceHeader !== !!upMetaRawOption.sourceHeader || dimensions; 
 | 
      resultSourceList = needsCreateSource ? [createSource(data, { 
 | 
        seriesLayoutBy: seriesLayoutBy, 
 | 
        sourceHeader: sourceHeader, 
 | 
        dimensions: dimensions 
 | 
      }, sourceFormat)] : []; 
 | 
    } else { 
 | 
      var datasetModel = sourceHost; 
 | 
      // Has upstream dataset. 
 | 
      if (hasUpstream) { 
 | 
        var result = this._applyTransform(upSourceMgrList); 
 | 
        resultSourceList = result.sourceList; 
 | 
        upstreamSignList = result.upstreamSignList; 
 | 
      } 
 | 
      // Is root dataset. 
 | 
      else { 
 | 
        var sourceData = datasetModel.get('source', true); 
 | 
        resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null)]; 
 | 
        upstreamSignList = []; 
 | 
      } 
 | 
    } 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      assert(resultSourceList && upstreamSignList); 
 | 
    } 
 | 
    this._setLocalSource(resultSourceList, upstreamSignList); 
 | 
  }; 
 | 
  SourceManager.prototype._applyTransform = function (upMgrList) { 
 | 
    var datasetModel = this._sourceHost; 
 | 
    var transformOption = datasetModel.get('transform', true); 
 | 
    var fromTransformResult = datasetModel.get('fromTransformResult', true); 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      assert(fromTransformResult != null || transformOption != null); 
 | 
    } 
 | 
    if (fromTransformResult != null) { 
 | 
      var errMsg = ''; 
 | 
      if (upMgrList.length !== 1) { 
 | 
        if (process.env.NODE_ENV !== 'production') { 
 | 
          errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset'; 
 | 
        } 
 | 
        doThrow(errMsg); 
 | 
      } 
 | 
    } 
 | 
    var sourceList; 
 | 
    var upSourceList = []; 
 | 
    var upstreamSignList = []; 
 | 
    each(upMgrList, function (upMgr) { 
 | 
      upMgr.prepareSource(); 
 | 
      var upSource = upMgr.getSource(fromTransformResult || 0); 
 | 
      var errMsg = ''; 
 | 
      if (fromTransformResult != null && !upSource) { 
 | 
        if (process.env.NODE_ENV !== 'production') { 
 | 
          errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult; 
 | 
        } 
 | 
        doThrow(errMsg); 
 | 
      } 
 | 
      upSourceList.push(upSource); 
 | 
      upstreamSignList.push(upMgr._getVersionSign()); 
 | 
    }); 
 | 
    if (transformOption) { 
 | 
      sourceList = applyDataTransform(transformOption, upSourceList, { 
 | 
        datasetIndex: datasetModel.componentIndex 
 | 
      }); 
 | 
    } else if (fromTransformResult != null) { 
 | 
      sourceList = [cloneSourceShallow(upSourceList[0])]; 
 | 
    } 
 | 
    return { 
 | 
      sourceList: sourceList, 
 | 
      upstreamSignList: upstreamSignList 
 | 
    }; 
 | 
  }; 
 | 
  SourceManager.prototype._isDirty = function () { 
 | 
    if (this._dirty) { 
 | 
      return true; 
 | 
    } 
 | 
    // All sourceList is from the some upstream. 
 | 
    var upSourceMgrList = this._getUpstreamSourceManagers(); 
 | 
    for (var i = 0; i < upSourceMgrList.length; i++) { 
 | 
      var upSrcMgr = upSourceMgrList[i]; 
 | 
      if ( 
 | 
      // Consider the case that there is ancestor diry, call it recursively. 
 | 
      // The performance is probably not an issue because usually the chain is not long. 
 | 
      upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) { 
 | 
        return true; 
 | 
      } 
 | 
    } 
 | 
  }; 
 | 
  /** 
 | 
   * @param sourceIndex By default 0, means "main source". 
 | 
   *                    In most cases there is only one source. 
 | 
   */ 
 | 
  SourceManager.prototype.getSource = function (sourceIndex) { 
 | 
    sourceIndex = sourceIndex || 0; 
 | 
    var source = this._sourceList[sourceIndex]; 
 | 
    if (!source) { 
 | 
      // Series may share source instance with dataset. 
 | 
      var upSourceMgrList = this._getUpstreamSourceManagers(); 
 | 
      return upSourceMgrList[0] && upSourceMgrList[0].getSource(sourceIndex); 
 | 
    } 
 | 
    return source; 
 | 
  }; 
 | 
  /** 
 | 
   * 
 | 
   * Get a data store which can be shared across series. 
 | 
   * Only available for series. 
 | 
   * 
 | 
   * @param seriesDimRequest Dimensions that are generated in series. 
 | 
   *        Should have been sorted by `storeDimIndex` asc. 
 | 
   */ 
 | 
  SourceManager.prototype.getSharedDataStore = function (seriesDimRequest) { 
 | 
    if (process.env.NODE_ENV !== 'production') { 
 | 
      assert(isSeries(this._sourceHost), 'Can only call getDataStore on series source manager.'); 
 | 
    } 
 | 
    var schema = seriesDimRequest.makeStoreSchema(); 
 | 
    return this._innerGetDataStore(schema.dimensions, seriesDimRequest.source, schema.hash); 
 | 
  }; 
 | 
  SourceManager.prototype._innerGetDataStore = function (storeDims, seriesSource, sourceReadKey) { 
 | 
    // TODO Can use other sourceIndex? 
 | 
    var sourceIndex = 0; 
 | 
    var storeList = this._storeList; 
 | 
    var cachedStoreMap = storeList[sourceIndex]; 
 | 
    if (!cachedStoreMap) { 
 | 
      cachedStoreMap = storeList[sourceIndex] = {}; 
 | 
    } 
 | 
    var cachedStore = cachedStoreMap[sourceReadKey]; 
 | 
    if (!cachedStore) { 
 | 
      var upSourceMgr = this._getUpstreamSourceManagers()[0]; 
 | 
      if (isSeries(this._sourceHost) && upSourceMgr) { 
 | 
        cachedStore = upSourceMgr._innerGetDataStore(storeDims, seriesSource, sourceReadKey); 
 | 
      } else { 
 | 
        cachedStore = new DataStore(); 
 | 
        // Always create store from source of series. 
 | 
        cachedStore.initData(new DefaultDataProvider(seriesSource, storeDims.length), storeDims); 
 | 
      } 
 | 
      cachedStoreMap[sourceReadKey] = cachedStore; 
 | 
    } 
 | 
    return cachedStore; 
 | 
  }; 
 | 
  /** 
 | 
   * PENDING: Is it fast enough? 
 | 
   * If no upstream, return empty array. 
 | 
   */ 
 | 
  SourceManager.prototype._getUpstreamSourceManagers = function () { 
 | 
    // Always get the relationship from the raw option. 
 | 
    // Do not cache the link of the dependency graph, so that 
 | 
    // there is no need to update them when change happens. 
 | 
    var sourceHost = this._sourceHost; 
 | 
    if (isSeries(sourceHost)) { 
 | 
      var datasetModel = querySeriesUpstreamDatasetModel(sourceHost); 
 | 
      return !datasetModel ? [] : [datasetModel.getSourceManager()]; 
 | 
    } else { 
 | 
      return map(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) { 
 | 
        return datasetModel.getSourceManager(); 
 | 
      }); 
 | 
    } 
 | 
  }; 
 | 
  SourceManager.prototype._getSourceMetaRawOption = function () { 
 | 
    var sourceHost = this._sourceHost; 
 | 
    var seriesLayoutBy; 
 | 
    var sourceHeader; 
 | 
    var dimensions; 
 | 
    if (isSeries(sourceHost)) { 
 | 
      seriesLayoutBy = sourceHost.get('seriesLayoutBy', true); 
 | 
      sourceHeader = sourceHost.get('sourceHeader', true); 
 | 
      dimensions = sourceHost.get('dimensions', true); 
 | 
    } 
 | 
    // See [REQUIREMENT_MEMO], `non-root-dataset` do not support them. 
 | 
    else if (!this._getUpstreamSourceManagers().length) { 
 | 
      var model = sourceHost; 
 | 
      seriesLayoutBy = model.get('seriesLayoutBy', true); 
 | 
      sourceHeader = model.get('sourceHeader', true); 
 | 
      dimensions = model.get('dimensions', true); 
 | 
    } 
 | 
    return { 
 | 
      seriesLayoutBy: seriesLayoutBy, 
 | 
      sourceHeader: sourceHeader, 
 | 
      dimensions: dimensions 
 | 
    }; 
 | 
  }; 
 | 
  return SourceManager; 
 | 
}(); 
 | 
export { SourceManager }; 
 | 
// Call this method after `super.init` and `super.mergeOption` to 
 | 
// disable the transform merge, but do not disable transform clone from rawOption. 
 | 
export function disableTransformOptionMerge(datasetModel) { 
 | 
  var transformOption = datasetModel.option.transform; 
 | 
  transformOption && setAsPrimitive(datasetModel.option.transform); 
 | 
} 
 | 
function isSeries(sourceHost) { 
 | 
  // Avoid circular dependency with Series.ts 
 | 
  return sourceHost.mainType === 'series'; 
 | 
} 
 | 
function doThrow(errMsg) { 
 | 
  throw new Error(errMsg); 
 | 
} 
 |