* Topological travel on Activity Network (Activity On Vertices). * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. * * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. * * If there is circle dependencey, Error will be thrown. *
(entity, dependencyGetter)
| 18702 | * |
| 18703 | */ |
| 18704 | function enableTopologicalTravel(entity, dependencyGetter) { |
| 18705 | |
| 18706 | /** |
| 18707 | * @public |
| 18708 | * @param {Array.<string>} targetNameList Target Component type list. |
| 18709 | * Can be ['aa', 'bb', 'aa.xx'] |
| 18710 | * @param {Array.<string>} fullNameList By which we can build dependency graph. |
| 18711 | * @param {Function} callback Params: componentType, dependencies. |
| 18712 | * @param {Object} context Scope of callback. |
| 18713 | */ |
| 18714 | entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { |
| 18715 | if (!targetNameList.length) { |
| 18716 | return; |
| 18717 | } |
| 18718 | |
| 18719 | var result = makeDepndencyGraph(fullNameList); |
| 18720 | var graph = result.graph; |
| 18721 | var stack = result.noEntryList; |
| 18722 | |
| 18723 | var targetNameSet = {}; |
| 18724 | each$1(targetNameList, function (name) { |
| 18725 | targetNameSet[name] = true; |
| 18726 | }); |
| 18727 | |
| 18728 | while (stack.length) { |
| 18729 | var currComponentType = stack.pop(); |
| 18730 | var currVertex = graph[currComponentType]; |
| 18731 | var isInTargetNameSet = !!targetNameSet[currComponentType]; |
| 18732 | if (isInTargetNameSet) { |
| 18733 | callback.call(context, currComponentType, currVertex.originalDeps.slice()); |
| 18734 | delete targetNameSet[currComponentType]; |
| 18735 | } |
| 18736 | each$1( |
| 18737 | currVertex.successor, |
| 18738 | isInTargetNameSet ? removeEdgeAndAdd : removeEdge |
| 18739 | ); |
| 18740 | } |
| 18741 | |
| 18742 | each$1(targetNameSet, function () { |
| 18743 | throw new Error('Circle dependency may exists'); |
| 18744 | }); |
| 18745 | |
| 18746 | function removeEdge(succComponentType) { |
| 18747 | graph[succComponentType].entryCount--; |
| 18748 | if (graph[succComponentType].entryCount === 0) { |
| 18749 | stack.push(succComponentType); |
| 18750 | } |
| 18751 | } |
| 18752 | |
| 18753 | // Consider this case: legend depends on series, and we call |
| 18754 | // chart.setOption({series: [...]}), where only series is in option. |
| 18755 | // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will |
| 18756 | // not be called, but only sereis.mergeOption is called. Thus legend |
| 18757 | // have no chance to update its local record about series (like which |
| 18758 | // name of series is available in legend). |
| 18759 | function removeEdgeAndAdd(succComponentType) { |
| 18760 | targetNameSet[succComponentType] = true; |
| 18761 | removeEdge(succComponentType); |
no test coverage detected