internal static void DoMerge(MergeOrder mergeOrder, XmlMerger merger) { XmlNode ours; XmlNode theirs; XmlNode common; DoPreMerge(mergeOrder, out ours, out theirs, out common); var results = merger.Merge(ours, theirs, common); DoPostMerge(mergeOrder.pathToOurs, results.MergedNode); }
internal static void DoMerge(MergeOrder mergeOrder, XmlMerger merger) { XmlNode ours; XmlNode theirs; XmlNode common; DoPreMerge(mergeOrder, out ours, out theirs, out common); // The document element is being returned here, so our parent isn't relevant and won't be used by the merge var results = merger.Merge(null, ours, theirs, common); DoPostMerge(mergeOrder.pathToOurs, results.MergedNode); }
private ChangeAndConflictAccumulator CheckOneWay(string ours, string theirs, string ancestor, params string[] xpaths) { XmlMerger m = new XmlMerger(new NullMergeSituation()); m.MergeStrategies.ElementStrategies.Add("a", ElementStrategy.CreateForKeyedElementInList("key")); m.MergeStrategies.ElementStrategies.Add("b", ElementStrategy.CreateForKeyedElementInList("key")); m.MergeStrategies.ElementStrategies.Add("c", ElementStrategy.CreateForKeyedElementInList("key")); m.MergeStrategies.ElementStrategies.Add("d", ElementStrategy.CreateForKeyedElementInList("key")); var result = m.Merge(ours, theirs, ancestor); foreach (string xpath in xpaths) { XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, xpath); } return result; }
public void MergeChildren_UsesNodeToGenerateContextDescriptorIfPossible() { string ancestor = @"<a> <b key='one'> <c key='a'>first</c> </b> </a>"; string red = ancestor; string blue = @"<a> <b key='one'> <c key='a'>first</c> <c key='b'>second</c> </b> </a>"; XmlMerger m = new XmlMerger(new NullMergeSituation()); m.MergeStrategies.ElementStrategies.Add("a", ElementStrategy.CreateForKeyedElementInList("key")); var strategy = ElementStrategy.CreateForKeyedElementInList("key"); var contextGenerator = new MockContextGenerator(); strategy.ContextDescriptorGenerator = contextGenerator; m.MergeStrategies.ElementStrategies.Add("b", strategy); m.MergeStrategies.ElementStrategies.Add("c", ElementStrategy.CreateForKeyedElementInList("key")); m.MergeStrategies.ElementStrategies.Add("d", ElementStrategy.CreateForKeyedElementInList("key")); m.Merge(red, blue, ancestor); Assert.That(contextGenerator.InputNode, Is.Not.Null); Assert.That(contextGenerator.InputNode.Name, Is.EqualTo("b")); }
private ChangeAndConflictAccumulator CheckOneWay(string ours, string theirs, string ancestor, MergeSituation situation, Dictionary<string, ElementStrategy> specialMergeStrategies, Action<string, ElementStrategy> adjustStrategy, params string[] xpaths) { var m = new XmlMerger(situation); AddMergeStrategies(m); if (specialMergeStrategies != null) { foreach (var kvp in specialMergeStrategies) m.MergeStrategies.ElementStrategies[kvp.Key] = kvp.Value; // don't use add, some may replace standard ones. } if (adjustStrategy != null) { foreach (var kvp in m.MergeStrategies.ElementStrategies) adjustStrategy(kvp.Key, kvp.Value); } var result = m.Merge(ours, theirs, ancestor); foreach (string xpath in xpaths) { XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, xpath); } return result; }
public void TextElement_WeEditedTheyDeleted_OursKept_ConflictRegistered() { string ancestor = @"<t>original</t>"; string ours = @"<t>mine</t>"; string theirs = @"<t></t>"; XmlMerger m = new XmlMerger(new NullMergeSituation()); var result = m.Merge(ours, theirs, ancestor); XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, "t[text()='mine']"); Assert.AreEqual(typeof(XmlTextEditVsRemovedConflict), result.Conflicts[0].GetType()); }
public void TextElement_EachEdited_OursKept_ConflictRegistered() { string ancestor = @"<t>original</t>"; string ours = @"<t>mine</t>"; string theirs = @"<t>theirs</t>"; XmlMerger m = new XmlMerger(new MergeSituation("pretendPath", "userX", "XRev","userY", "YRev", MergeOrder.ConflictHandlingModeChoices.WeWin)); var result = m.Merge(ours, theirs, ancestor); XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, "t[text()='mine']"); Assert.AreEqual("pretendPath", result.Conflicts[0].RelativeFilePath); Assert.AreEqual(typeof(XmlTextBothEditedTextConflict), result.Conflicts[0].GetType()); }
public static string DoMerge( MergeStrategies mergeStrategies, MergeSituation mergeSituation, string ancestorXml, string ourXml, string theirXml, IEnumerable<string> xpathQueriesThatMatchExactlyOneNode, IEnumerable<string> xpathQueriesThatReturnNull, int expectedConflictCount, List<Type> expectedConflictTypes, int expectedChangesCount, List<Type> expectedChangeTypes) { var doc = new XmlDocument(); var ourNode = XmlUtilities.GetDocumentNodeFromRawXml(ourXml, doc); var theirNode = XmlUtilities.GetDocumentNodeFromRawXml(theirXml, doc); var ancestorNode = XmlUtilities.GetDocumentNodeFromRawXml(ancestorXml, doc); var eventListener = new ListenerForUnitTests(); var merger = new XmlMerger(mergeSituation) { MergeStrategies = mergeStrategies }; var retval = merger.Merge(eventListener, ourNode, theirNode, ancestorNode).OuterXml; Assert.AreSame(eventListener, merger.EventListener); // Make sure it never changes it, while we aren't looking, since at least one Merge method does that very thing. CheckMergeResults(retval, eventListener, xpathQueriesThatMatchExactlyOneNode, xpathQueriesThatReturnNull, expectedConflictCount, expectedConflictTypes, expectedChangesCount, expectedChangeTypes); return retval; }
public void EnsureMergedCData_IsRetained() { using (var common = TempFile.WithFilename("common.ChorusNotes")) using (var ours = TempFile.WithFilename("ours.ChorusNotes")) using (var theirs = TempFile.WithFilename("theirs.ChorusNotes")) { const string commonData = @"<?xml version='1.0' encoding='utf-8'?> <notes version='0'> <annotation class='mergeConflict' ref='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' guid='1cb66d60-90d5-4367-95b1-b7b41eb8986d'> <message author='merger' status='open' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z'>Entry 'pintu': user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.<![CDATA[<conflict typeGuid='3d9ba4ac-4a25-11df-9879-0800200c9a66' class='Chorus.merge.xml.generic.EditedVsRemovedElementConflict' relativeFilePath='Linguistics\Lexicon\Lexicon.lexdb' type='Removed Vs Edited Element Conflict' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z' whoWon='user57' htmlDetails='<head><style type='text/css'></style></head><body><div class='description'>Entry "pintu": user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.</div><div class='alternative'>user57's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 <span style="text-decoration: line-through; color: red">13:46:3.625</span><span style="background: Yellow">14:14:20.218</span>" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;AStr</span> <span style="background: Yellow">ws="en"></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Run</span> <span style="background: Yellow">ws="en">a</span> <span style="background: Yellow">door</span><span style="background: Yellow">&lt;/Run></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/AStr></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='alternative'>user57@tpad2's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='mergechoice'>The merger kept the change made by user57</div></body>' contextPath='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' contextDataLabel='Entry "pintu"'> <MergeSituation alphaUserId='user57' betaUserId='user57@tpad2' alphaUserRevision='306520fcc148' betaUserRevision='5aa248710fbc' path='Linguistics\Lexicon\Lexicon.lexdb' conflictHandlingMode='WeWin' /> </conflict>]]></message> <message author='user57' status='closed' date='2012-07-20T22:49:03Z' guid='bf43783e-eca1-4b0f-bacd-6fe168d7d616'></message> </annotation> </notes>"; File.WriteAllText(common.Path, commonData); const string ourData = @"<?xml version='1.0' encoding='utf-8'?> <notes version='0'> <annotation class='mergeConflict' ref='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' guid='1cb66d60-90d5-4367-95b1-b7b41eb8986d'> <message author='merger' status='open' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z'>Entry 'pintu': user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.<![CDATA[<conflict typeGuid='3d9ba4ac-4a25-11df-9879-0800200c9a66' class='Chorus.merge.xml.generic.EditedVsRemovedElementConflict' relativeFilePath='Linguistics\Lexicon\Lexicon.lexdb' type='Removed Vs Edited Element Conflict' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z' whoWon='user57' htmlDetails='<head><style type='text/css'></style></head><body><div class='description'>Entry "pintu": user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.</div><div class='alternative'>user57's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 <span style="text-decoration: line-through; color: red">13:46:3.625</span><span style="background: Yellow">14:14:20.218</span>" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;AStr</span> <span style="background: Yellow">ws="en"></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Run</span> <span style="background: Yellow">ws="en">a</span> <span style="background: Yellow">door</span><span style="background: Yellow">&lt;/Run></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/AStr></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='alternative'>user57@tpad2's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='mergechoice'>The merger kept the change made by user57</div></body>' contextPath='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' contextDataLabel='Entry "pintu"'> <MergeSituation alphaUserId='user57' betaUserId='user57@tpad2' alphaUserRevision='306520fcc148' betaUserRevision='5aa248710fbc' path='Linguistics\Lexicon\Lexicon.lexdb' conflictHandlingMode='WeWin' /> </conflict>]]></message> <message author='user57' status='closed' date='2012-07-20T22:49:03Z' guid='bf43783e-eca1-4b0f-bacd-6fe168d7d616'></message> <message author='user57' status='open' date='2012-07-20T23:11:24Z' guid='524786f4-8e27-4ebf-b7ea-02846723c2d8'>Chorus seems to have chosen the better gloss anyway.</message> </annotation> </notes>"; File.WriteAllText(ours.Path, ourData); const string theirData = @"<?xml version='1.0' encoding='utf-8'?> <notes version='0'> <annotation class='mergeConflict' ref='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' guid='1cb66d60-90d5-4367-95b1-b7b41eb8986d'> <message author='merger' status='open' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z'>Entry 'pintu': user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.<![CDATA[<conflict typeGuid='3d9ba4ac-4a25-11df-9879-0800200c9a66' class='Chorus.merge.xml.generic.EditedVsRemovedElementConflict' relativeFilePath='Linguistics\Lexicon\Lexicon.lexdb' type='Removed Vs Edited Element Conflict' guid='ef89b532-5441-48a8-aea9-065b6ab5cfbd' date='2012-07-20T14:18:35Z' whoWon='user57' htmlDetails='<head><style type='text/css'></style></head><body><div class='description'>Entry "pintu": user57@tpad2 deleted this element, while user57 edited it. The automated merger kept the change made by user57.</div><div class='alternative'>user57's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 <span style="text-decoration: line-through; color: red">13:46:3.625</span><span style="background: Yellow">14:14:20.218</span>" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;AStr</span> <span style="background: Yellow">ws="en"></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;Run</span> <span style="background: Yellow">ws="en">a</span> <span style="background: Yellow">door</span><span style="background: Yellow">&lt;/Run></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/AStr></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="background: Yellow">&lt;/Definition></span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='alternative'>user57@tpad2's changes: &lt;LexEntry guid="bab7776e-531b-4ce1-997f-fa638c09e381"><br/>&nbsp;&nbsp;&lt;DateCreated val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DateModified val="2012-7-20 13:46:3.625" /><br/>&nbsp;&nbsp;&lt;DoNotUseForParsing val="False" /><br/>&nbsp;&nbsp;&lt;HomographNumber val="0" /><br/>&nbsp;&nbsp;&lt;LexemeForm><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemAllomorph guid="556f6e08-0fb2-4171-82e0-6dcdddf9490b"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="id">pintu&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Form><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;IsAbstract val="False" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="d7f713e8-e8cf-11d3-9764-00c04f186933" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphType><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MoStemAllomorph><br/>&nbsp;&nbsp;&lt;/LexemeForm><br/>&nbsp;&nbsp;&lt;MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;MoStemMsa guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" /><br/>&nbsp;&nbsp;&lt;/MorphoSyntaxAnalyses><br/>&nbsp;&nbsp;&lt;Senses><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;ownseq class="LexSense" guid="dad069de-dfad-45f6-a5d2-449265adbc3a"><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;AUni ws="en">door&lt;/AUni><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Gloss><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;objsur guid="f63e03f0-ac9d-4b1b-980f-316bbb741f70" t="r" /><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/MorphoSyntaxAnalysis><br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ownseq><br/>&nbsp;&nbsp;&lt;/Senses><br/>&lt;/LexEntry></div><div class='mergechoice'>The merger kept the change made by user57</div></body>' contextPath='silfw://localhost/link?app=flex&database=current&server=&tool=default&guid=bab7776e-531b-4ce1-997f-fa638c09e381&tag=&label=Entry "pintu"' contextDataLabel='Entry "pintu"'> <MergeSituation alphaUserId='user57' betaUserId='user57@tpad2' alphaUserRevision='306520fcc148' betaUserRevision='5aa248710fbc' path='Linguistics\Lexicon\Lexicon.lexdb' conflictHandlingMode='WeWin' /> </conflict>]]></message> <message author='user57' status='closed' date='2012-07-20T22:49:03Z' guid='bf43783e-eca1-4b0f-bacd-6fe168d7d616'></message> <message author='user57' status='closed' date='2012-07-20T23:11:27Z' guid='a0481907-3fff-45a2-bb1c-961c3198c86a'></message> </annotation> </notes>"; File.WriteAllText(theirs.Path, theirData); // Do it the new way. _chorusNotesFileHandler.Do3WayMerge(new MergeOrder(ours.Path, common.Path, theirs.Path, new NullMergeSituation())); var newWayResult = File.ReadAllText(ours.Path); CheckResults(false, ourData, newWayResult); // Do it the old way via XmlMerge. var mergeSit = new MergeSituation(ours.Path, "Me", "8", "You", "9", MergeOrder.ConflictHandlingModeChoices.WeWin); var merger = new XmlMerger(mergeSit); var listener = new ListenerForUnitTests(); merger.MergeStrategies.SetStrategy("annotation", ElementStrategy.CreateForKeyedElement("guid", false)); var messageStrategy = ElementStrategy.CreateForKeyedElement("guid", false); messageStrategy.IsImmutable = true; merger.MergeStrategies.SetStrategy("message", messageStrategy); merger.EventListener = listener; var mergeResult = merger.Merge( XmlUtilities.GetDocumentNodeFromRawXml(ourData.Replace("<?xml version='1.0' encoding='utf-8'?>", null).Trim(), new XmlDocument()), XmlUtilities.GetDocumentNodeFromRawXml(theirData.Replace("<?xml version='1.0' encoding='utf-8'?>", null).Trim(), new XmlDocument()), XmlUtilities.GetDocumentNodeFromRawXml(commonData.Replace("<?xml version='1.0' encoding='utf-8'?>", null).Trim(), new XmlDocument())); var oldWayResult = mergeResult.MergedNode.OuterXml; CheckResults(false, ourData, oldWayResult); // Compare old and new results. CheckResults(true, newWayResult, oldWayResult); using (var log = new ChorusNotesMergeEventListener(ours.Path)) { // The purpose here is to make sure that the listener works correctly regarding maintaining CData. // I (RandyR) saw a merged data set where the CData material was not maintained. } var result = File.ReadAllText(ours.Path); CheckResults(true, newWayResult, result); var doc = new XmlDocument(); doc.Load(ours.Path); // This is how the AnnotationRepository class writes out an updated ChorusNotes file. using (var writer = XmlWriter.Create(ours.Path, CanonicalXmlSettings.CreateXmlWriterSettings())) { doc.Save(writer); } CheckResults(true, result, File.ReadAllText(ours.Path)); } }