예제 #1
0
        private void OnMatch( DiffgramParentOperation parent, bool bNeedPosition )
        {
            EditScriptMatch matchOp = _editScript as EditScriptMatch;

            Debug.Assert( _curSourceIndex == matchOp._firstSourceIndex + matchOp._length - 1 );
            Debug.Assert( _curTargetIndex == matchOp._firstTargetIndex + matchOp._length - 1 );

            // cache
            int endTargetIndex = matchOp._firstTargetIndex + matchOp._length - 1;
            int endSourceIndex = matchOp._firstSourceIndex + matchOp._length - 1;
            XmlDiffNode targetRoot = _targetNodes[ endTargetIndex ];
            XmlDiffNode sourceRoot = _sourceNodes[ endSourceIndex ];

            // a subtree or leaf node matches
            if ( matchOp._firstTargetIndex <= targetRoot.Left  &&
             matchOp._firstSourceIndex <= sourceRoot.Left )
            {
            if ( _bBuildingAddTree )
            {
                Debug.Assert( !bNeedPosition );

                ulong opid = GenerateOperationID( XmlDiffDescriptorType.Move );

                // output <add match=" "> to diffgram and "remove" to substitute script
                parent.InsertAtBeginning( new DiffgramCopy( sourceRoot, true, opid ) );

                // add 'remove' operation to postponed operations
                PostponedRemoveSubtrees( sourceRoot, opid,
                //AddToPosponedOperations( new DiffgramRemoveSubtrees( sourceRoot, opid ),
                                        sourceRoot.Left,
                                        endSourceIndex );
            }
            else
            {
                // matched element -> check attributes if they really match (hash values of attributes matches)
                if ( sourceRoot.NodeType == XmlDiffNodeType.Element )
                {
                    DiffgramPosition diffPos = _cachedDiffgramPosition;
                    diffPos._sourceNode = sourceRoot;

                    GenerateChangeDiffgramForAttributes( diffPos, (XmlDiffElement)sourceRoot, (XmlDiffElement)targetRoot );

                    if ( diffPos._firstChildOp != null || bNeedPosition )
                    {
                        parent.InsertAtBeginning( diffPos );
                        _cachedDiffgramPosition = new DiffgramPosition( null );
                        bNeedPosition = false;
                    }
                }
                // otherwise output <node> - only if we need the position (<=> preceding operation was 'add')
                else
                {
                    if ( bNeedPosition )
                    {
                        parent.InsertAtBeginning( new DiffgramPosition( sourceRoot ) );
                        bNeedPosition = false;
                    }
                    // xml declaration, DTD
                    else if ( !_bChildOrderSignificant && (int)sourceRoot.NodeType < 0 ) {
                        DiffgramOperation op = parent._firstChildOp;
                        if ( op is DiffgramAddNode || op is DiffgramAddSubtrees || op is DiffgramCopy ) {
                            parent.InsertAtBeginning( new DiffgramPosition( sourceRoot ) );
                        }
                    }
                }
            }

            // adjust current position
            _curSourceIndex = sourceRoot.Left - 1;
            _curTargetIndex = targetRoot.Left - 1;

            // adjust boundaries in the edit script or move to next edit script operation
            matchOp._length -= endTargetIndex - targetRoot.Left + 1;
            if ( matchOp._length <= 0 )
                _editScript = _editScript._nextEditScript;
            }
            // single but non-leaf node matches (-> recursively generate the diffgram subtree)
            else
            {
            // adjust current position
            _curSourceIndex--;
            _curTargetIndex--;

            // adjust boundaries in the edit script or move to next edit script operation
            matchOp._length--;
            if ( matchOp._length <= 0 )
                _editScript = _editScript._nextEditScript;

            DiffgramParentOperation diffgramNode;
            if ( _bBuildingAddTree )
            {
                Debug.Assert( !bNeedPosition );

                ulong opid = GenerateOperationID( XmlDiffDescriptorType.Move );
                bool bCopySubtree = sourceRoot.NodeType != XmlDiffNodeType.Element;

                // output <add match=".." subtree="no">
                diffgramNode = new DiffgramCopy( sourceRoot, bCopySubtree, opid );
                // add 'remove' operation to postponed operations
                PostponedRemoveNode( sourceRoot, bCopySubtree, opid,
                                     endSourceIndex,
                                     endSourceIndex );

                // recursively generate the diffgram subtree
                GenerateDiffgramAdd( diffgramNode, sourceRoot.Left, targetRoot.Left );

                // insert to diffgram tree
                parent.InsertAtBeginning( diffgramNode );
            }
            else
            {
                // output <node>
                diffgramNode = new DiffgramPosition( sourceRoot );

                // recursively generate the diffgram subtree
                GenerateDiffgramMatch( diffgramNode, sourceRoot.Left, targetRoot.Left );

                // insert to diffgram tree
                if ( diffgramNode._firstChildOp != null )
                    parent.InsertAtBeginning( diffgramNode );
            }
            }
        }
예제 #2
0
 private void WalkTreeOnMatchNode( DiffgramParentOperation diffParent, XmlDiffNode sourceNode, XmlDiffNode targetNode, ref XmlDiffNode needPositionSourceNode )
 {
     if ( sourceNode.HasChildNodes || targetNode.HasChildNodes ) {
     DiffgramPosition diffMatch = new DiffgramPosition( sourceNode );
     WalkTreeGenerateDiffgramMatch( diffMatch, (XmlDiffParentNode)sourceNode, (XmlDiffParentNode)targetNode );
     diffParent.InsertAtEnd( diffMatch );
     needPositionSourceNode = null;
     }
     else {
     if ( sourceNode.NodeType == XmlDiffNodeType.ShrankNode ) {
         needPositionSourceNode = ((XmlDiffShrankNode)sourceNode)._lastNode;
     }
     else {
         needPositionSourceNode = sourceNode;
     }
     }
 }
예제 #3
0
        // produces <change> element in diffgram
        private void OnChange( DiffgramParentOperation parent )
        {
            EditScriptChange chOp = _editScript as EditScriptChange;

            Debug.Assert( chOp._targetIndex == _curTargetIndex );
            Debug.Assert( chOp._sourceIndex == _curSourceIndex );

            XmlDiffNode sourceRoot = _sourceNodes[ chOp._sourceIndex ];
            XmlDiffNode targetRoot = _targetNodes[ chOp._targetIndex ];

            Debug.Assert( !( sourceRoot is XmlDiffShrankNode) );
            Debug.Assert( !( targetRoot is XmlDiffShrankNode) );

            // adjust current position
            _curSourceIndex--;
            _curTargetIndex--;

            // move to next edit script operation
            _editScript = _editScript._nextEditScript;

            DiffgramOperation diffgramNode = null;

            if ( _bBuildingAddTree )
            {
            // <add> changed node to the new location
            if ( targetRoot.NodeType == XmlDiffNodeType.Element )
                diffgramNode = new DiffgramAddNode( targetRoot, 0 );
            else
                diffgramNode = new DiffgramAddSubtrees( targetRoot, 0, !_xmlDiff.IgnoreChildOrder );

            // <remove> old node from old location -> add to postponed operations
            bool bSubtree = sourceRoot.NodeType != XmlDiffNodeType.Element;
            PostponedRemoveNode( sourceRoot, bSubtree, 0,
            //AddToPosponedOperations( new DiffgramRemoveNode( sourceRoot, bSubtree, 0 ),
                chOp._sourceIndex, chOp._sourceIndex );

            // recursively process children
            if ( sourceRoot.Left < chOp._sourceIndex ||
                targetRoot.Left < chOp._targetIndex )
            {
                Debug.Assert( targetRoot.NodeType == XmlDiffNodeType.Element );
                GenerateDiffgramAdd( (DiffgramParentOperation)diffgramNode, sourceRoot.Left, targetRoot.Left );
            }

            // add attributes, if element
            if ( targetRoot.NodeType == XmlDiffNodeType.Element )
                GenerateAddDiffgramForAttributes( (DiffgramParentOperation)diffgramNode, (XmlDiffElement)targetRoot );
            }
            else
            {
            ulong opid = 0;

            // change of namespace or prefix -> get the appropriate operation id
            if ( !_xmlDiff.IgnoreNamespaces &&
                 sourceRoot.NodeType == XmlDiffNodeType.Element )
            {
                XmlDiffElement sourceEl = (XmlDiffElement)sourceRoot;
                XmlDiffElement targetEl = (XmlDiffElement)targetRoot;

                if ( sourceEl.LocalName == targetEl.LocalName )
                {
                    opid = GetNamespaceChangeOpid( sourceEl.NamespaceURI, sourceEl.Prefix,
                                                   targetEl.NamespaceURI, targetEl.Prefix );
                }
            }

            if ( sourceRoot.NodeType == XmlDiffNodeType.Element )
            {
                if ( XmlDiff.IsChangeOperationOnAttributesOnly( chOp._changeOp ) )
                    diffgramNode = new DiffgramPosition( sourceRoot );
                else
                {
                    Debug.Assert( (int)chOp._changeOp == (int)XmlDiffOperation.ChangeElementName ||
                                  ( (int)chOp._changeOp >= (int)XmlDiffOperation.ChangeElementNameAndAttr1 &&
                                    (int)chOp._changeOp <= (int)XmlDiffOperation.ChangeElementNameAndAttr2 ) );

                    diffgramNode = new DiffgramChangeNode( sourceRoot, targetRoot, XmlDiffOperation.ChangeElementName, opid );
                }

                // recursively process children
                if ( sourceRoot.Left < chOp._sourceIndex ||
                    targetRoot.Left < chOp._targetIndex )
                {
                    GenerateDiffgramMatch( (DiffgramParentOperation) diffgramNode, sourceRoot.Left, targetRoot.Left );
                }

                GenerateChangeDiffgramForAttributes( (DiffgramParentOperation)diffgramNode, (XmlDiffElement)sourceRoot, (XmlDiffElement)targetRoot );
            }
            else
            {
                // '<change>'
                diffgramNode = new DiffgramChangeNode( sourceRoot, targetRoot, chOp._changeOp, opid );
                Debug.Assert( !sourceRoot.HasChildNodes );
            }
            }

            parent.InsertAtBeginning( diffgramNode );
        }
예제 #4
0
        private void WalkTreeOnChangeElement( DiffgramParentOperation diffParent, XmlDiffElement sourceElement, XmlDiffElement targetElement, XmlDiffOperation op )
        {
            DiffgramParentOperation diffOp;

            if ( XmlDiff.IsChangeOperationOnAttributesOnly( op ) ) {
            diffOp = new DiffgramPosition( sourceElement );
            }
            else
            {
            ulong opid = 0;
            if ( !_xmlDiff.IgnoreNamespaces && sourceElement.LocalName == targetElement.LocalName)
            {
                opid = GetNamespaceChangeOpid( sourceElement.NamespaceURI, sourceElement.Prefix,
                                               targetElement.NamespaceURI, targetElement.Prefix );
            }

            Debug.Assert( (int)op >= (int)XmlDiffOperation.ChangeElementName &&
                          (int)op <= (int)XmlDiffOperation.ChangeElementNameAndAttr3 );

            diffOp = new DiffgramChangeNode( sourceElement, targetElement, XmlDiffOperation.ChangeElementName, opid );
            }

            GenerateChangeDiffgramForAttributes( diffOp, sourceElement, targetElement );

            if ( sourceElement.HasChildNodes || targetElement.HasChildNodes ) {
            WalkTreeGenerateDiffgramMatch( diffOp, sourceElement, targetElement );
            }

            diffParent.InsertAtEnd( diffOp );
        }