/// <summary> /// Adds to the operations list all operations required to mutate /// <paramref name="originalNode"/> to the state* of /// <paramref name="newNode"/>. /// </summary> /// <param name="originalNode">The original node.</param> /// <param name="newNode">The new node.</param> /// <param name="ops">The operations list to add to.</param> /// <param name="idGenerator">The temporary ID generator for ADD operations.</param> /// <returns>The set of child product dimensions that require further /// processing.</returns> private void AddMutateOperations(ProductPartitionNode originalNode, ProductPartitionNode newNode, List <OperationPair> ops, TemporaryIdGenerator idGenerator) { NodeDifference nodeDifference = Diff(originalNode, newNode, dimensionComparator); bool isProcessChildren; switch (nodeDifference) { case NodeDifference.NEW_NODE: ops.AddRange(CreateAddOperations(newNode, idGenerator)); // No need to further process children. The ADD operations above will include operations // for all children of newNode. isProcessChildren = false; break; case NodeDifference.REMOVED_NODE: ops.Add(CreateRemoveOperation(originalNode)); // No need to further process children. The REMOVE operation above will perform a // cascading delete of all children of newNode. isProcessChildren = false; break; case NodeDifference.PARTITION_TYPE_CHANGE: case NodeDifference.EXCLUDED_UNIT_CHANGE: ops.Add(CreateRemoveOperation(originalNode)); ops.AddRange(CreateAddOperations(newNode, idGenerator)); // No need to further process children. The ADD operations above will include operations // for all children of newNode. isProcessChildren = false; break; case NodeDifference.BID_CHANGE: // Ensure that the new node has the proper ID (this may have been lost if the node // was removed and then re-added). newNode.ProductPartitionId = originalNode.ProductPartitionId; ops.Add(CreateSetBidOperation(newNode)); // Process the children of newNode. The SET operation above will only handle changes // made to newNode, not its children. isProcessChildren = true; break; case NodeDifference.NONE: // Ensure that the new node has the proper ID (this may have been lost if the node // was removed and then re-added). newNode.ProductPartitionId = originalNode.ProductPartitionId; // This node does not have changes, but its children may. isProcessChildren = true; break; default: throw new InvalidOperationException("Unrecognized difference: " + nodeDifference); } if (isProcessChildren) { // Try to match the children in new and original trees to identify the // matching dimensions. foreach (ProductPartitionNode newChild in newNode.Children) { if (originalNode.HasChild(newChild.Dimension)) { // this is probably an edit. AddMutateOperations(originalNode.GetChild(newChild.Dimension), newChild, ops, idGenerator); } else { // this is a new node. AddMutateOperations(null, newChild, ops, idGenerator); } } foreach (ProductPartitionNode originalChild in originalNode.Children) { if (newNode.HasChild(originalChild.Dimension)) { // this is probably an edit. We dealt with it before continue; } else { // this is a removed node. AddMutateOperations(originalChild, null, ops, idGenerator); } } } }