private void addMutateOperationsByParent(ProductPartitionNode originalParentNode,
      ProductPartitionNode newParentNode, Set<ProductDimension> childDimensionsToProcess,
      List<OperationPair> ops) {
    for (ProductDimension dimensionToProcess : childDimensionsToProcess) {
      ProductPartitionNode originalChild = originalParentNode.hasChild(dimensionToProcess)
              ? originalParentNode.getChild(dimensionToProcess)
              : null;
      ProductPartitionNode newChild = newParentNode.hasChild(dimensionToProcess)
              ? newParentNode.getChild(dimensionToProcess)
              : null;
      Set<ProductDimension> grandchildDimensionsToProcess =
          addMutateOperations(originalChild, newChild, ops);
      if (!grandchildDimensionsToProcess.isEmpty()) {
        // Logic check - the only condition where further processing of children is required
        // is when the parent exists in both trees. If the parent is null in one tree but
        // not the other, then the node for dimensionToProcess was either:
        // 1) removed from the original OR
        // 2) added to the new tree
        // In both cases, the call to addMutateOperations above will have already added all of the
        // necessary operations to handle the node and all of its children.
        Preconditions.checkState(originalChild != null,
            "Original child should not be null if there are children to process");
        Preconditions.checkState(newChild != null,
            "New child should not be null if there are children to process");
        addMutateOperationsByParent(originalChild, newChild, grandchildDimensionsToProcess, ops);
      }
    }
  }
private void addMutateOperationsByParent ( ProductPartitionNode originalParentNode , ProductPartitionNode newParentNode , Set < ProductDimension > childDimensionsToProcess , List < OperationPair > ops ) { for ( ProductDimension dimensionToProcess : childDimensionsToProcess ) { ProductPartitionNode originalChild = originalParentNode . hasChild ( dimensionToProcess ) ? originalParentNode . getChild ( dimensionToProcess ) : null ; ProductPartitionNode newChild = newParentNode . hasChild ( dimensionToProcess ) ? newParentNode . getChild ( dimensionToProcess ) : null ; Set < ProductDimension > grandchildDimensionsToProcess = addMutateOperations ( originalChild , newChild , ops ) ; if ( ! grandchildDimensionsToProcess . isEmpty ( ) ) { Preconditions . checkState ( originalChild != null , "Original child should not be null if there are children to process" ) ; Preconditions . checkState ( newChild != null , "New child should not be null if there are children to process" ) ; addMutateOperationsByParent ( originalChild , newChild , grandchildDimensionsToProcess , ops ) ; } } }
Adds to the operations list all operations required to mutate the children of
{@code originalParentNode} to {@code newParentNode}.

@param originalParentNode required - must not be null
@param newParentNode required - must not be null
@param childDimensionsToProcess the child dimensions to process
@param ops the operations list to add to