internal bool TryAdd(TNode node1, TNode node2) { Debug.Assert(_comparer.TreesEqual(node1, _root1)); Debug.Assert(_comparer.TreesEqual(node2, _root2)); if (_oneToTwo.ContainsKey(node1) || _twoToOne.ContainsKey(node2)) { return(false); } _oneToTwo.Add(node1, node2); _twoToOne.Add(node2, node1); return(true); }
internal Match(TNode root1, TNode root2, TreeComparer <TNode> comparer, IEnumerable <KeyValuePair <TNode, TNode> > knownMatches) { _root1 = root1; _root2 = root2; _comparer = comparer; int labelCount = comparer.LabelCount; CategorizeNodesByLabels(comparer, root1, labelCount, out var nodes1, out var count1); CategorizeNodesByLabels(comparer, root2, labelCount, out var nodes2, out var count2); _oneToTwo = new Dictionary <TNode, TNode>(); _twoToOne = new Dictionary <TNode, TNode>(); // Root nodes always match. Add them before adding known matches to make sure we always have root mapping. TryAdd(root1, root2); if (knownMatches != null) { foreach (var knownMatch in knownMatches) { if (comparer.GetLabel(knownMatch.Key) != comparer.GetLabel(knownMatch.Value)) { throw new ArgumentException(string.Format(WorkspacesResources.Matching_nodes_0_and_1_must_have_the_same_label, knownMatch.Key, knownMatch.Value), nameof(knownMatches)); } if (!comparer.TreesEqual(knownMatch.Key, root1)) { throw new ArgumentException(string.Format(WorkspacesResources.Node_0_must_be_contained_in_the_old_tree, knownMatch.Key), nameof(knownMatches)); } if (!comparer.TreesEqual(knownMatch.Value, root2)) { throw new ArgumentException(string.Format(WorkspacesResources.Node_0_must_be_contained_in_the_new_tree, knownMatch.Value), nameof(knownMatches)); } // skip pairs whose key or value is already mapped: TryAdd(knownMatch.Key, knownMatch.Value); } } ComputeMatch(nodes1, nodes2); }