private Operation AddNode()

in libraries/AdaptiveExpressions/TriggerTrees/Node.cs [182:353]


        private Operation AddNode(Node triggerNode, Dictionary<Node, Operation> ops)
        {
            var op = Operation.None;
            if (!ops.TryGetValue(this, out op))
            {
                var trigger = triggerNode.Triggers[0];
                var relationship = Relationship(triggerNode);
#if TraceTree
                if (Node.ShowTrace)
                {
                    Debug.WriteLine("");
#if Count
                    Debug.Write($"{_count}:");
#endif
                    Debug.WriteLine(this);
                    Debug.WriteLine($"{relationship}");
                    Debug.WriteLine(triggerNode);
                }
#endif
#if Count
                ++_count;
#endif
                switch (relationship)
                {
                    case RelationshipType.Equal:
                        {
                            // Ensure action is not already there
                            var found = false;
                            foreach (var existing in _allTriggers)
                            {
                                if (trigger.Action != null && trigger.Action.Equals(existing.Action))
                                {
                                    found = true;
                                    break;
                                }
                            }

                            op = Operation.Found;
                            if (!found)
                            {
                                _allTriggers.Add(trigger);
                                var add = true;
                                for (var i = 0; i < _triggers.Count;)
                                {
                                    var existing = _triggers[i];
                                    var reln = trigger.Relationship(existing, Tree.Comparers);
                                    if (reln == RelationshipType.Generalizes)
                                    {
#if TraceTree
                                        if (Node.ShowTrace) Debug.WriteLine($"Trigger specialized by {existing}");
#endif
                                        add = false;
                                        break;
                                    }
                                    else if (reln == RelationshipType.Specializes)
                                    {
#if TraceTree
                                        if (Node.ShowTrace) Debug.WriteLine($"Trigger replaces {existing}");
#endif
                                        _triggers.RemoveAt(i);
                                    }
                                    else
                                    {
                                        ++i;
                                    }
                                }

                                if (add)
                                {
#if TraceTree
                                    if (Node.ShowTrace) Debug.WriteLine("Add trigger");
#endif
                                    _triggers.Add(trigger);
                                }
#if DEBUG
                                Debug.Assert(CheckInvariants(), "invariants bad");
#endif
                                op = Operation.Added;
                            }
                        }

                        break;
                    case RelationshipType.Incomparable:
                        {
                            foreach (var child in _specializations)
                            {
                                child.AddNode(triggerNode, ops);
                            }
                        }

                        break;
                    case RelationshipType.Specializes:
                        {
                            triggerNode.AddSpecialization(this);
                            op = Operation.Inserted;
                        }

                        break;
                    case RelationshipType.Generalizes:
                        {
                            var foundOne = false;
                            List<Node> removals = null;
#if TraceTree
                            if (Node.ShowTrace) ++Debug.IndentLevel;
#endif
                            foreach (var child in _specializations)
                            {
                                var childOp = child.AddNode(triggerNode, ops);
                                if (childOp != Operation.None)
                                {
                                    foundOne = true;
                                    if (childOp == Operation.Inserted)
                                    {
                                        if (removals == null)
                                        {
                                            removals = new List<Node>();
                                        }

                                        removals.Add(child);
                                        op = Operation.Added;
                                    }
                                    else
                                    {
                                        op = childOp;
                                    }
                                }
                            }
#if TraceTree
                            if (Node.ShowTrace) --Debug.IndentLevel;
#endif
                            if (removals != null)
                            {
                                foreach (var child in removals)
                                {
                                    _specializations.Remove(child);
                                }
#if TraceTree
                                if (Node.ShowTrace)
                                {
                                    Debug.WriteLine("Generalized");
                                    foreach (var removal in removals)
                                    {
                                        Debug.WriteLine(removal);
                                    }
                                    Debug.WriteLine($"in {this}");
                                }
#endif
                                _specializations.Add(triggerNode);
#if DEBUG
                                Debug.Assert(CheckInvariants(), "bad invariants");
#endif
                            }

                            if (!foundOne)
                            {
                                _specializations.Add(triggerNode);
#if DEBUG
                                Debug.Assert(CheckInvariants(), "bad invariants");
#endif
                                op = Operation.Added;
                            }
                        }

                        break;
                }

                // Prevent visiting this node again
                ops[this] = op;
            }

            return op;
        }