private void AddItem(GraphMap <TKey, TNode, TEdge> map, IGraphCommon element, TKey parentKey)
        {
            switch (element)
            {
            case NodeMap <TKey> node:
                map.Add((TNode)CreateNode(node.Key));

                if (!EqualityComparer <TKey> .Default.Equals(parentKey, default(TKey)))
                {
                    map.Add((TEdge)CreateEdge(parentKey, node.Key));
                }

                foreach (var child in node)
                {
                    AddItem(map, child, node.Key);
                }
                break;

            case SequenceMap <TKey> sequence:
                TKey linkParent = parentKey;
                bool first      = true;

                foreach (var child in sequence)
                {
                    AddItem(map, child, parentKey);

                    if (child is IGraphNode <TKey> childNode)
                    {
                        if (!first)
                        {
                            map.Add((TEdge)CreateDependsOnEdge(childNode.Key, linkParent));
                        }
                        else
                        {
                            first = false;
                        }

                        linkParent = childNode.Key;
                    }
                }

                break;

            case IGraphNode <TKey> node:
                map.Add((TNode)CreateNode(node.Key));
                break;

            case GraphEdge <TKey> edge:
                map.Add((TEdge)CreateEdge(edge.FromNodeKey, edge.ToNodeKey));
                break;

            case GraphDependOnEdge <TKey> edge:
                map.Add((TEdge)CreateDependsOnEdge(edge.FromNodeKey, edge.ToNodeKey));
                break;

            default:
                throw new ArgumentException($"Not supported type: {element.GetType()}");
            }
        }
        /// <summary>
        /// Create orchestrator host
        /// </summary>
        /// <param name="graph">graph to be executed</param>
        /// <param name="jobHost">job host to use</param>
        /// <param name="maxParallel">max number of parallel task, if null or 0, there is no limit</param>
        public OrchestratorHost(GraphMap <TKey, TNode, TEdge> graph, IJobHost jobHost, int?maxParallel = null)
        {
            graph.Verify(nameof(graph)).IsNotNull();
            jobHost.Verify(nameof(jobHost)).IsNotNull();
            maxParallel.Verify(nameof(maxParallel)).Assert(x => x == null || x >= 0, "value must be greater then or equal to zero");

            _graph   = graph;
            _jobHost = jobHost;

            _runningKeys = new HashSet <TKey>(_graph.KeyCompare);
            _maxParallel = maxParallel;
            _semaphore   = maxParallel > 0 ? _semaphore = new SemaphoreSlim((int)maxParallel, (int)maxParallel) : null;
        }
        public OrchestratorBuilder(GraphMap <TKey, TNode, TEdge> graph)
        {
            graph.Verify(nameof(graph)).IsNotNull();

            Graph = graph;
        }