/// <summary> /// For parsing EXCEL Input. Handles the finalization of a processed node. /// </summary> /// <param name="_n">the node to be finalized (no unresolved subnodes remaining)</param> /// <param name="_level">the Level of the node in the _nodeTree_FIN</param> /// <param name="_nodeTree_FIN">Tree of finalized nodes</param> /// <param name="_nodeList_FIN">List of unique synched finalized nodes</param> /// <param name="_nodeStack_OPEN">stack of unfinished nodes</param> /// <param name="_nodeLevelStack_OPEN">stackof the levels of the unfinished nodes</param> /// <param name="_nodeContNamesStack_OPEN">stack of the not yet preocessed subnode names of the unfinished nodes</param> /// <param name="_ids_finalized">the IDs of the finalized nodes (due to the tree structure there can be more than just _n)</param> private static void FinalizeNode(Node _n, int _level, ref List <Node> _nodeTree_FIN, ref List <Node> _nodeList_FIN, ref Stack <Node> _nodeStack_OPEN, ref Stack <int> _nodeLevelStack_OPEN, ref Stack <List <string> > _nodeContNamesStack_OPEN, ref List <long> _ids_finalized) { if (_n == null || _nodeTree_FIN == null || _nodeList_FIN == null || _nodeStack_OPEN == null || _nodeLevelStack_OPEN == null || _nodeContNamesStack_OPEN == null || _ids_finalized == null) { return; } int nrNodesOnStack = _nodeStack_OPEN.Count; if (nrNodesOnStack != _nodeLevelStack_OPEN.Count || nrNodesOnStack != _nodeContNamesStack_OPEN.Count) { return; } // 0: mark the node as finalized _ids_finalized.Add(_n.ID); // 1: remove node from the unfinished stacks, if it was on them if (nrNodesOnStack > 0) { Node n_on_top = _nodeStack_OPEN.Peek(); if (n_on_top.ID == _n.ID) { _nodeStack_OPEN.Pop(); _nodeLevelStack_OPEN.Pop(); _nodeContNamesStack_OPEN.Pop(); } } // 2: add node to the list of unique synced finished nodes NodeAssembler.AddNodeToListofFinishedNodes(_n, ref _nodeList_FIN); // 3: ATTACH node if (_level == NodeAssembler.NODE_ROOT_LEVEL) { // add node to the tree of finalized nodes _nodeTree_FIN.Add(_n); } else { // attach to a node on the unfinished stacks ONE LEVEL higher if (_nodeStack_OPEN.Count > 0) { int nL_at_top_of_stack = _nodeLevelStack_OPEN.Peek(); List <string> nCN_at_top_of_stack = _nodeContNamesStack_OPEN.Peek(); if (_level == nL_at_top_of_stack + 1 && nCN_at_top_of_stack.Contains(_n.NodeName)) { // add the finalized LOWER-LEVEL node to the most recent node ONE LEVEL HIGHER Node n_at_top_of_stack = _nodeStack_OPEN.Peek(); n_at_top_of_stack.AddNode(_n); nCN_at_top_of_stack.Remove(_n.NodeName); // check to see if the node ONE LEVEL HIGHER has just been finished if (nCN_at_top_of_stack.Count == 0) { NodeAssembler.FinalizeNode(n_at_top_of_stack, nL_at_top_of_stack, ref _nodeTree_FIN, ref _nodeList_FIN, ref _nodeStack_OPEN, ref _nodeLevelStack_OPEN, ref _nodeContNamesStack_OPEN, ref _ids_finalized); } } } } }
private static List <Node> ConvertNodeAndLevelInfoToNodeList(List <Node> _nodes_at_allLevels, List <string> _nodes_names, List <List <string> > _nodes_contained_node_names, List <int> _nodes_levels) { List <Node> nodeTree_FIN = new List <Node>(); // contains all finished nodes of level 0 List <Node> nodeList_FIN = new List <Node>(); // contains UNIQUE SYNCED FINISHED nodes of various levels Stack <Node> nodeStack_OPEN = new Stack <Node>(); Stack <int> nodeLevelStack_OPEN = new Stack <int>(); Stack <List <string> > nodeContNamesStack_OPEN = new Stack <List <string> >(); List <long> ids_remaining = _nodes_at_allLevels.Select(x => x.ID).ToList(); int nrR = ids_remaining.Count; int nrTotal = nrR; int nrIterations = 0; //string debug = ""; while (nrR > 0 && nrIterations < NodeAssembler.MAX_NR_ITERATIONS) { for (int i = 0; i < nrTotal; i++) { // take current node, if not processed yet if (!ids_remaining.Contains(_nodes_at_allLevels[i].ID)) { continue; } Node n = _nodes_at_allLevels[i]; int nL = _nodes_levels[i]; List <string> nCN = _nodes_contained_node_names[i]; // add node to the open stack nodeStack_OPEN.Push(n); nodeLevelStack_OPEN.Push(nL); nodeContNamesStack_OPEN.Push(nCN); #region DEBUG //debug += "i=" + i + " taken: " + _nodes_at_allLevels[i].NodeName + " at L" + _nodes_levels[i] + "\n"; //debug += "FINISHED TREE\n"; //foreach (Node ntf in nodeTree_FIN) //{ // debug += ntf.ToString() + "\n"; //} //debug += "\nFINISHED NODES\n"; //foreach (Node ntl in nodeList_FIN) //{ // debug += ntl.ToString() + "\n"; //} //debug += "\nOPEN STACK\n"; //foreach (Node nso in nodeStack_OPEN) //{ // debug += nso.ToString() + "\n"; //} //debug += "\n"; #endregion // PROCESS NODE -> try to resolve the contained node names if (nCN.Count != 0) { List <string> to_remove = new List <string>(); int index_last_following_CN = i + 1; foreach (string name in nCN) { // the name is not from an explicit node definition -> produce it here if (!_nodes_names.Contains(name)) { Node subN = new Node(name, string.Empty, Node.NO_DATA, Node.NO_DATA, Node.NO_DATA, true, false); nodeTree_FIN.Add(subN); NodeAssembler.AddNodeToListofFinishedNodes(subN, ref nodeList_FIN); n.AddNode(subN); to_remove.Add(name); continue; } // check if there isn't an unprocessed node FOLLOWING in the input node list if (nrIterations == 0 && index_last_following_CN <= nrTotal - 1) { int index; bool found = NodeAssembler.LookAhead(name, nL + 1, _nodes_at_allLevels, _nodes_levels, index_last_following_CN, out index); if (found) { index_last_following_CN = index + 1; continue; // ... and wait for it } } // contained node has not been processed yet -> wait int ind = nodeList_FIN.FindIndex(x => x.NodeName == name); if (ind < 0 || ind >= nodeList_FIN.Count) { continue; } // add a DEEP copy of the found node as a subnode to the current one Node copy = new Node(nodeList_FIN[ind], true); copy.NodeSource = "Copy"; n.AddNode(copy); to_remove.Add(name); //debug += "made deep copy\n\n"; } foreach (string name in to_remove) { nCN.Remove(name); } } // FINALIZE NODE if (nCN.Count == 0) { List <long> ids_finalized = new List <long>(); NodeAssembler.FinalizeNode(n, nL, ref nodeTree_FIN, ref nodeList_FIN, ref nodeStack_OPEN, ref nodeLevelStack_OPEN, ref nodeContNamesStack_OPEN, ref ids_finalized); foreach (long id in ids_finalized) { ids_remaining.Remove(id); } } } nrIterations++; nrR = ids_remaining.Count; nodeStack_OPEN.Clear(); nodeLevelStack_OPEN.Clear(); nodeContNamesStack_OPEN.Clear(); } return(nodeTree_FIN); }