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;
}