Beispiel #1
0
        private XmlNode FindMatchingNode(XmlNode node, XmlNode otherParent, HashSet <XmlNode> acceptableTargets)
        {
            IFindNodeToMerge finder = _merger.MergeStrategies.GetMergePartnerFinder(node);
            var result = finder.GetNodeToMerge(node, otherParent, acceptableTargets);

            // This check allows implementations where there is only one possible match to ignore acceptableTargets
            // and just give us the one match from otherParent. If we don't want it, we discard it.
            if (!acceptableTargets.Contains(result))
            {
                return(null);
            }
            return(result);
        }
Beispiel #2
0
 public OptionalKeyAttrFinder(string key, IFindNodeToMerge backupFinder)
 {
     _key    = key;
     _backup = backupFinder;
 }
 private static void AddKeyedElementType(IDictionary<string, ElementStrategy> sharedElementStrategies, string elementName, IFindNodeToMerge findBykeyAttribute, bool orderOfTheseIsRelevant, bool isAtomic)
 {
     var strategy = new ElementStrategy(orderOfTheseIsRelevant)
                     {
                         MergePartnerFinder = findBykeyAttribute,
                         ContextDescriptorGenerator = ContextGen,
                         IsAtomic = isAtomic
                     };
     sharedElementStrategies.Add(elementName, strategy);
 }
 public OptionalKeyAttrFinder(string key, IFindNodeToMerge backupFinder)
 {
     _key = key;
     _backup = backupFinder;
 }
Beispiel #5
0
        /// <summary>
        /// Determine possible correspondences for the given range of currently unmatched items.
        /// </summary>
        /// <param name="startPrimaryRange"></param>
        /// <param name="endPrimaryRange"></param>
        private void MakePossibleCorrespondences(int startPrimaryRange, int endPrimaryRange)
        {
            if (startPrimaryRange == -1)
            {
                return;                  // empty range
            }
            int limPrimaryRange = endPrimaryRange + 1;
            int startOtherRange = 0;
            int limOtherRange   = _positions.Length;

            if (startPrimaryRange > 0)
            {
                startOtherRange = _indexInPositions[_correspondences[_primary[startPrimaryRange - 1]]] + 1;
            }
            if (endPrimaryRange < _primary.Count - 1)
            {
                limOtherRange = _indexInPositions[_correspondences[_primary[limPrimaryRange]]];
            }
            if (limOtherRange - startOtherRange <= 0)
            {
                return;                 // no objects that might correspond
            }
            List <XmlNode> possibleMatches = new List <XmlNode>(limOtherRange - startOtherRange);

            for (int i = startOtherRange; i < limOtherRange; i++)
            {
                possibleMatches.Add(_positions[i].Other);
            }

            for (int iPrimary = startPrimaryRange; iPrimary < limPrimaryRange; iPrimary++)
            {
                XmlNode                  ourChild       = _primary[iPrimary];
                IFindNodeToMerge         finder         = _merger.MergeStrategies.GetMergePartnerFinder(ourChild);
                IFindPossibleNodeToMerge possibleFinder = finder as IFindPossibleNodeToMerge;
                if (possibleFinder == null)
                {
                    continue;
                }
                XmlNode otherChild = possibleFinder.GetPossibleNodeToMerge(ourChild, possibleMatches);
                if (otherChild == null)
                {
                    continue;
                }
                // We don't want to reorder things here, so future searches are limited to subsequent
                // possible matches.
                possibleMatches.RemoveRange(0, possibleMatches.IndexOf(otherChild) + 1);
                _correspondences[ourChild] = otherChild;

                // Take advantage of the new match to reduce ambiguity.
                int iPositionChanged = _indexInPositions[otherChild];
                _positions[iPositionChanged].exactPosition = iPrimary;
                for (int ipos = iPositionChanged + 1; ipos < limOtherRange; ipos++)
                {
                    _positions[ipos].indexofPrecedingPrimaryNode = iPrimary;
                }
                for (int ipos = iPositionChanged - 1;
                     ipos >= startOtherRange && _positions[ipos].exactPosition == -1;
                     ipos--)
                {
                    _positions[ipos].indexOfFollowingPrimaryNode = iPrimary;
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Remove from ancestorKeepers any node that does not correspond to anything (both deleted)
        /// Remove from ancestorKeepers and theirKeepers any pair that correspond to each other but not to anything in ours. Report conflict (delete/edit) if pair not identical.
        /// Remove from ancestorKeepers and ourKeepers any pair that correspond to each other and are identical, but don't correspond to anything in theirs (they deleted)
        /// Report conflict (edit/delete) on any pair that correspond in ours and ancestor, but nothing in theirs, and that are NOT identical. (but keep them...we win)
        /// </summary>
        private void DoDeletions()
        {
            // loop over a copy of the list, since we may modify ancestorKeepers.
            List <XmlNode> loopSource    = new List <XmlNode>(_childrenOfAncestorKeepers);
            var            ourChildSet   = new HashSet <XmlNode>(_ours == null ? new XmlNode[0] : _ours.ChildNodes.Cast <XmlNode>());
            var            theirChildSet = new HashSet <XmlNode>(_theirs == null ? new XmlNode[0] : _theirs.ChildNodes.Cast <XmlNode>());

            foreach (XmlNode ancestorChild in loopSource)
            {
                ElementStrategy  mergeStrategy = _merger.MergeStrategies.GetElementStrategy(ancestorChild);
                IFindNodeToMerge finder        = mergeStrategy.MergePartnerFinder;
                XmlNode          ourChild      = finder.GetNodeToMerge(ancestorChild, _ours, ourChildSet);
                XmlNode          theirChild    = finder.GetNodeToMerge(ancestorChild, _theirs, theirChildSet);

                var extantNode = ancestorChild ?? ourChild ?? theirChild;
                if (extantNode is XmlCharacterData)
                {
                    return;                     // Already done.
                }
                if (XmlUtilities.IsTextLevel(ourChild, theirChild, ancestorChild))
                {
                    new MergeTextNodesMethod(_merger, mergeStrategy, _skipInnerMergeFor,
                                             ref ourChild, _childrenOfOurKeepers,
                                             theirChild, _childrenOfTheirKeepers,
                                             ancestorChild, _childrenOfAncestorKeepers).DoDeletions();
                }
                else if (ourChild == null)
                {
                    // We deleted it.
                    if (theirChild == null)
                    {
                        // We both deleted it. Forget it ever existed.
                        // Route tested: MergeChildrenMethodTests.
                        _merger.EventListener.ChangeOccurred(new XmlBothDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild));
                        _childrenOfAncestorKeepers.Remove(ancestorChild);
                    }
                    else
                    {
                        if (!XmlUtilities.AreXmlElementsEqual(ancestorChild, theirChild))
                        {
                            // We deleted, they modified, report conflict.
                            if (theirChild.NodeType == XmlNodeType.Element)
                            {
                                // Route tested (XmlMergerTests).
                                _merger.ConflictOccurred(
                                    new RemovedVsEditedElementConflict(theirChild.Name, null,
                                                                       theirChild, ancestorChild,
                                                                       _merger.MergeSituation,
                                                                       _merger.MergeStrategies.GetElementStrategy(theirChild),
                                                                       _merger.MergeSituation.BetaUserId),
                                    theirChild);
                                _skipInnerMergeFor.Add(theirChild);
                            }
                            else
                            {
                                // Never used. But then, there isn't plain text in an xml file.
                                _merger.ConflictOccurred(
                                    new RemovedVsEditedTextConflict(null, theirChild,
                                                                    ancestorChild,
                                                                    _merger.MergeSituation,
                                                                    _merger.MergeSituation.BetaUserId));
                                _skipInnerMergeFor.Add(theirChild);
                            }
                            _childrenOfAncestorKeepers.Remove(ancestorChild);                            //review hatton added dec 2009, wanting whoever edited it to win (previously "we" always won)
                        }
                        else
                        {
                            //We deleted it, they didn't edit it. So just make it go away.
                            // Route tested in TextElementMergeTests, MergeChildrenMethod_DiffOnlyTests, XmlMergerTests
                            _merger.EventListener.ChangeOccurred(new XmlDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild, theirChild));
                            _childrenOfAncestorKeepers.Remove(ancestorChild);
                            _childrenOfTheirKeepers.Remove(theirChild);
                        }
                    }
                }
                else if (theirChild == null)
                {
                    // they deleted it (and we didn't)
                    if (XmlUtilities.AreXmlElementsEqual(ancestorChild, ourChild))
                    {
                        // We didn't touch it, allow their deletion to go forward, forget it existed.
                        // Route tested (XmlMergerTests).
                        _merger.EventListener.ChangeOccurred(new XmlDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild, ourChild));
                        _childrenOfAncestorKeepers.Remove(ancestorChild);
                        _childrenOfOurKeepers.Remove(ourChild);
                    }
                    else
                    {
                        // We changed it, ignore their deletion and report conflict.
                        if (ourChild.NodeType == XmlNodeType.Element)
                        {
                            // Route tested (XmlMergerTests).
                            _merger.ConflictOccurred(
                                new EditedVsRemovedElementConflict(ourChild.Name, ourChild, null, ancestorChild,
                                                                   _merger.MergeSituation, _merger.MergeStrategies.GetElementStrategy(ourChild), _merger.MergeSituation.AlphaUserId),
                                ourChild);
                            _skipInnerMergeFor.Add(ourChild);
                        }
                        else
                        {
                            // Never used. But then, there isn't plain text in an xml file.
                            _merger.ConflictOccurred(
                                new EditedVsRemovedTextConflict(ourChild, null, ancestorChild, _merger.MergeSituation, _merger.MergeSituation.AlphaUserId));
                            _skipInnerMergeFor.Add(ourChild);
                        }
                    }
                }
            }
        }
Beispiel #7
0
        private static void AddKeyedElementType(IDictionary <string, ElementStrategy> sharedElementStrategies, string elementName, IFindNodeToMerge findBykeyAttribute, bool orderOfTheseIsRelevant, bool isAtomic)
        {
            var strategy = new ElementStrategy(orderOfTheseIsRelevant)
            {
                MergePartnerFinder         = findBykeyAttribute,
                ContextDescriptorGenerator = ContextGen,
                IsAtomic = isAtomic
            };

            sharedElementStrategies.Add(elementName, strategy);
        }