private void OnRemove( DiffgramParentOperation parent ) { EditScriptRemove remOp = _editScript as EditScriptRemove; Debug.Assert( remOp._endSourceIndex == _curSourceIndex ); XmlDiffNode sourceRoot = _sourceNodes[ remOp._endSourceIndex ]; // remove subtree or leaf node and no descendant node matches (=has been moved somewhere else) if ( remOp._startSourceIndex <= sourceRoot.Left ) { bool bShrankNode = sourceRoot is XmlDiffShrankNode; if ( sourceRoot._bSomeDescendantMatches && !bShrankNode ) { DiffgramOperation newDiffOp = GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)sourceRoot ); if ( _bBuildingAddTree ) { PostponedOperation( newDiffOp, sourceRoot.Left, remOp._endSourceIndex ); } else { parent.InsertAtBeginning( newDiffOp ); } } else { ulong opid = 0; // shrank node -> output as 'move' operation if ( bShrankNode ) { XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) sourceRoot; if ( shrankNode.MoveOperationId == 0 ) shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move ); opid = shrankNode.MoveOperationId; Debug.Assert( sourceRoot == _sourceNodes[ sourceRoot.Left ] ); } // insert 'remove' operation if ( _bBuildingAddTree ) { PostponedRemoveSubtrees( sourceRoot, opid, //AddToPosponedOperations( new DiffgramRemoveSubtrees( sourceRoot, opid ), sourceRoot.Left, remOp._endSourceIndex ); } else { if ( opid != 0 || !parent.MergeRemoveSubtreeAtBeginning( sourceRoot ) ) { parent.InsertAtBeginning( new DiffgramRemoveSubtrees( sourceRoot, opid, !_xmlDiff.IgnoreChildOrder ) ); } } } // adjust current position _curSourceIndex = sourceRoot.Left - 1; // adjust boundaries in the edit script or move to next edit script operation remOp._endSourceIndex = sourceRoot.Left - 1; if ( remOp._startSourceIndex > remOp._endSourceIndex ) _editScript = _editScript._nextEditScript; } // remove single but non-leaf node or some descendant matches (=has been moved somewhere else) // -> recursively process diffgram subtree else { Debug.Assert( !( sourceRoot is XmlDiffShrankNode) ); // adjust current position _curSourceIndex--; // adjust boundaries in the edit script or move to next edit script operation remOp._endSourceIndex--; if ( remOp._startSourceIndex > remOp._endSourceIndex ) _editScript = _editScript._nextEditScript; bool bRemoveSubtree = sourceRoot.NodeType != XmlDiffNodeType.Element; if ( _bBuildingAddTree ) { // add 'remove' to postponed operations PostponedRemoveNode( sourceRoot, bRemoveSubtree, 0, //AddToPosponedOperations( new DiffgramRemoveNode( sourceRoot, bRemoveSubtree, 0 ), remOp._endSourceIndex + 1, remOp._endSourceIndex + 1 ); // recursively parse subtree GenerateDiffgramAdd( parent, sourceRoot.Left, _targetNodes[ _curTargetIndex ].Left ); } else { // 'remove' operation DiffgramRemoveNode remNode = new DiffgramRemoveNode( sourceRoot, bRemoveSubtree, 0 ); // parse subtree GenerateDiffgramMatch( remNode, sourceRoot.Left, _targetNodes[ _curTargetIndex ].Left ); parent.InsertAtBeginning( remNode ); } } }
private DiffgramOperation GenerateDiffgramRemoveWhenDescendantMatches( XmlDiffNode sourceParent ) { Debug.Assert( sourceParent._bSomeDescendantMatches ); Debug.Assert( sourceParent.NodeType != XmlDiffNodeType.ShrankNode ); DiffgramParentOperation diffOp = new DiffgramRemoveNode( sourceParent, false, 0 ); XmlDiffNode child = ((XmlDiffParentNode)sourceParent)._firstChildNode; while ( child != null ) { if ( child.NodeType == XmlDiffNodeType.ShrankNode ) { XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) child; if ( shrankNode.MoveOperationId == 0 ) shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move ); diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, shrankNode.MoveOperationId, !_xmlDiff.IgnoreChildOrder ) ); } else if ( child.HasChildNodes && child._bSomeDescendantMatches ) { diffOp.InsertAtEnd( GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)child ) ); } else { if ( !diffOp.MergeRemoveSubtreeAtEnd( child ) ) diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, 0, !_xmlDiff.IgnoreChildOrder ) ); } child = child._nextSibling; } return diffOp; }