private static ElementStrategy CreateStrategyForKeyedElement(string guid, bool orderIsRelevant) { var result = ElementStrategy.CreateForKeyedElement(guid, orderIsRelevant); result.ContextDescriptorGenerator = ContextGen; return(result); }
private void SetupElementStrategies() { _annotationMerger.MergeStrategies.SetStrategy("annotation", ElementStrategy.CreateForKeyedElement("guid", false)); var messageStrategy = ElementStrategy.CreateForKeyedElement("guid", false); messageStrategy.IsImmutable = true; _annotationMerger.MergeStrategies.SetStrategy("message", messageStrategy); }
public void Run_WeEditedTextElementInsideOneOfTWoKeyedElements_ListenerGetsTextEditReport() { // Gets report from MergeTextNodesMethod string ours = @"<a><b id='foo'>new</b> <b id='gaa'>same</b></a>"; string ancestor = @"<a><b id='foo'>old</b> <b id='gaa'>same</b></a>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); merger.MergeStrategies.SetStrategy("b", ElementStrategy.CreateForKeyedElement("id", false)); TestCompare <XmlTextChangedReport>(merger, ours, ancestor, "//a"); }
/// <summary> /// Bootstrap a merger for the new-styled (nested) files. /// </summary> /// <remarks> /// 1. A generic 'header' element will be handled, although it may not appear in the file. /// 2. All classes will be included. /// 3. Merge strategies for class properties (regular or custom) will have keys of "classname+propname" to make them unique, system-wide. /// </remarks> private static void BootstrapSystem(MetadataCache metadataCache, XmlMerger merger) { merger.MergeStrategies.ElementToMergeStrategyKeyMapper = new FieldWorksElementToMergeStrategyKeyMapper(); var sharedElementStrategies = new Dictionary <string, ElementStrategy>(); CreateSharedElementStrategies(sharedElementStrategies); var strategiesForMerger = merger.MergeStrategies; ContextGen.MergeStrategies = strategiesForMerger; foreach (var sharedKvp in sharedElementStrategies) { strategiesForMerger.SetStrategy(sharedKvp.Key, sharedKvp.Value); } var customPropDefnStrat = new ElementStrategy(false) { MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> { SharedConstants.Name, SharedConstants.Class }), ContextDescriptorGenerator = new FieldWorksCustomPropertyContextGenerator(), IsAtomic = true, NumberOfChildren = NumberOfChildrenAllowed.Zero }; strategiesForMerger.SetStrategy(SharedConstants.CustomField, customPropDefnStrat); var headerStrategy = CreateSingletonElementType(false); headerStrategy.ContextDescriptorGenerator = ContextGen; strategiesForMerger.SetStrategy(SharedConstants.Header, headerStrategy); // There are two abstract class names used: CmAnnotation and DsChart. // Chorus knows how to find the matching element for these, as they use <CmAnnotation class='concreteClassname'. // So, add a keyed strategy for each of them. var keyedStrat = ElementStrategy.CreateForKeyedElement(SharedConstants.GuidStr, false); keyedStrat.AttributesToIgnoreForMerging.Add(SharedConstants.Class); keyedStrat.AttributesToIgnoreForMerging.Add(SharedConstants.GuidStr); strategiesForMerger.SetStrategy(SharedConstants.CmAnnotation, keyedStrat); keyedStrat = ElementStrategy.CreateForKeyedElement(SharedConstants.GuidStr, false); keyedStrat.AttributesToIgnoreForMerging.Add(SharedConstants.Class); keyedStrat.AttributesToIgnoreForMerging.Add(SharedConstants.GuidStr); strategiesForMerger.SetStrategy(SharedConstants.DsChart, keyedStrat); foreach (var classInfo in metadataCache.AllConcreteClasses) { MakeClassStrategy(strategiesForMerger, classInfo, ContextGen); AddPropertyStrategiesForClass(strategiesForMerger, classInfo); } }
public void TheyDeleteNeighborsAndWeInsertInOrder() { // Some in MergeTextNodesMethod. One in MergeChildrenMethod const string ancestor = @"<a> <b key='one'> <c key='a'>first</c> <c key='b'>second</c> <c key='c'>third</c> <c key='d'>fourth</c> </b> </a>" ; const string ours = @"<a> <b key='one'> <c key='a'>first</c> <c key='b'>second</c> <c key='z'>extra</c> <c key='c'>third</c> <c key='d'>fourth</c> </b> </a>" ; const string theirs = @"<a> <b key='one'> <c key='a'>first</c> <c key='d'>fourth</c> </b> </a>" ; _mergeStrategies = new MergeStrategies(); _mergeStrategies.ElementStrategies.Add("a", ElementStrategy.CreateSingletonElement()); _mergeStrategies.ElementStrategies.Add("b", ElementStrategy.CreateForKeyedElement("key", true)); _mergeStrategies.ElementStrategies.Add("c", ElementStrategy.CreateForKeyedElement("key", true)); XmlTestHelper.DoMerge( _mergeStrategies, ancestor, ours, theirs, new List <string> { "a/b[@key='one']/c[1][@key='a' and text()='first']", "a/b[@key='one']/c[2][@key='z' and text()='extra']", "a/b[@key='one']/c[3][@key='d' and text()='fourth']" }, new List <string> { "a/b[@key='one']/c[@key='b']", "a/b[@key='one']/c[@key='c']" }, 0, null, 3, new List <Type> { typeof(XmlTextDeletedReport), typeof(XmlTextDeletedReport), typeof(XmlTextAddedReport) }); }
public void Run_BothMovedDifferentKeyedNodes_OrderIrrelevant_NoDuplicatesCreated() { string ours = @"<foo><gloss lang='c'/><gloss lang='b'/><gloss lang='a'/></foo>"; string theirs = @"<foo><gloss lang='a'/><gloss lang='c'/><gloss lang='b'/></foo>"; string ancestor = @"<foo><gloss lang='a'/><gloss lang='b'/><gloss lang='c'/></foo>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); merger.MergeStrategies.SetStrategy("foo", ElementStrategy.CreateSingletonElement()); merger.MergeStrategies.SetStrategy("gloss", ElementStrategy.CreateForKeyedElement("lang", false)); TestMergeWithoutConflicts(merger, ours, theirs, ancestor, "//foo"); }
private MergeResult CheckOneWay(string ours, string theirs, string ancestor, params string[] xpaths) { XmlMerger m = new XmlMerger(); m._mergeStrategies._elementStrategies.Add("a", ElementStrategy.CreateForKeyedElement("key")); m._mergeStrategies._elementStrategies.Add("b", ElementStrategy.CreateForKeyedElement("key")); m._mergeStrategies._elementStrategies.Add("c", ElementStrategy.CreateForKeyedElement("key")); MergeResult result = m.Merge(ours, theirs, ancestor, false); foreach (string xpath in xpaths) { XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, xpath); } return(result); }
public void Run_BothAddedDifferentKeyedNodes_OrderIrrelevant_NoConflict() { string ours = @"<foo><gloss lang='a'> <text>aGloss</text> </gloss></foo>" ; string theirs = @"<foo><gloss lang='b'> <text>bGloss</text> </gloss></foo>" ; string ancestor = @"<foo/>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); merger.MergeStrategies.SetStrategy("gloss", ElementStrategy.CreateForKeyedElement("lang", false)); merger.MergeStrategies.SetStrategy("text", ElementStrategy.CreateSingletonElement()); TestMergeWithoutConflicts(merger, ours, theirs, ancestor, "//foo"); }
public void Run_BothAddedDifferentKeyedNodes_OrderIsRelevant_OrderAmbiguityConflict() { string ours = @"<sense id='123'><gloss lang='a'> <text>aGloss</text> </gloss></sense>" ; string theirs = @"<sense id='123'><gloss lang='b'> <text>bGloss</text> </gloss></sense>" ; string ancestor = @"<sense id='123'></sense>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); merger.MergeStrategies.SetStrategy("sense", ElementStrategy.CreateForKeyedElement("id", true)); merger.MergeStrategies.SetStrategy("gloss", ElementStrategy.CreateForKeyedElement("lang", true)); merger.MergeStrategies.SetStrategy("text", ElementStrategy.CreateSingletonElement()); TestMerge <AmbiguousInsertConflict>(merger, ours, theirs, ancestor, "//sense"); }
public void Run_BothChangedKeyedNode_GetBothEditedConflict() { string ours = @"<sense id='123'><gloss lang='a'> <text>ourGloss</text> </gloss></sense>" ; string theirs = @"<sense id='123'><gloss lang='a'> <text>theirGloss</text> </gloss></sense>" ; string ancestor = @"<sense id='123'><gloss lang='a'> <text>original</text> </gloss></sense>" ; XmlMerger merger = new XmlMerger(new NullMergeSituation()); //without this stategy, we'd get an AmbiguousInsertConflict merger.MergeStrategies.SetStrategy("text", ElementStrategy.CreateSingletonElement()); merger.MergeStrategies.SetStrategy("sense", ElementStrategy.CreateForKeyedElement("id", true)); merger.MergeStrategies.SetStrategy("gloss", ElementStrategy.CreateForKeyedElement("lang", true)); TestMerge <XmlTextBothEditedTextConflict>(merger, ours, theirs, ancestor, "//sense"); }
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 ourDataNode = XmlUtilities.GetDocumentNodeFromRawXml(ourData.Replace("<?xml version='1.0' encoding='utf-8'?>", null).Trim(), new XmlDocument()); var mergeResult = merger.Merge( ourDataNode.ParentNode, ourDataNode, 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)); } }
public void ElementStrategy_CreateForKeyedElement_Has_FindByKeyAttribute_Finder() { var elementStrategy = ElementStrategy.CreateForKeyedElement("myKey", false); Assert.IsInstanceOf <FindByKeyAttribute>(elementStrategy.MergePartnerFinder); }
public void DeleteAtomicElementVsModifyHasConflict() { const string commonAncestor = @"<Lexicon> <LexEntry guid='ffdc58c9-5cc3-469f-9118-9f18c0138d02'> <MorphoSyntaxAnalyses> <MoStemMsa guid='33adabe9-a02e-42cb-b942-277a7be5c841'> <PartOfSpeech> <objsur guid='e72dbc59-e93f-4df2-b6bd-39a53e331201' t='r' /> </PartOfSpeech> </MoStemMsa> </MorphoSyntaxAnalyses> <Senses/> </LexEntry> </Lexicon>"; const string matthew = @"<Lexicon> <LexEntry guid='ffdc58c9-5cc3-469f-9118-9f18c0138d02'> <MorphoSyntaxAnalyses> <MoStemMsa guid='33adabe9-a02e-42cb-b942-277a7be5c841'> <PartOfSpeech> <objsur guid='f92dbc59-e93f-4df2-b6bd-39a53e331201' t='r' /> </PartOfSpeech> </MoStemMsa> </MorphoSyntaxAnalyses> <Senses/> </LexEntry> </Lexicon>"; const string lee = @"<Lexicon> <LexEntry guid='ffdc58c9-5cc3-469f-9118-9f18c0138d02'> <MorphoSyntaxAnalyses> <MoStemMsa guid='33adabe9-a02e-42cb-b942-277a7be5c841'> <PartOfSpeech /> </MoStemMsa> </MorphoSyntaxAnalyses> <Senses/> </LexEntry> </Lexicon>"; var listener = new ListenerForUnitTests(); var merger = new XmlMerger(new NullMergeSituation()) { EventListener = listener }; merger.MergeStrategies.SetStrategy("Lexicon", ElementStrategy.CreateSingletonElement()); var strat = ElementStrategy.CreateForKeyedElement("guid", false); strat.AttributesToIgnoreForMerging.Add("guid"); merger.MergeStrategies.SetStrategy("LexEntry", strat); strat = ElementStrategy.CreateSingletonElement(); strat.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne; merger.MergeStrategies.SetStrategy("MorphoSyntaxAnalyses", strat); strat = ElementStrategy.CreateForKeyedElement("guid", false); strat.AttributesToIgnoreForMerging.Add("guid"); merger.MergeStrategies.SetStrategy("MoStemMsa", strat); strat = ElementStrategy.CreateSingletonElement(); strat.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne; merger.MergeStrategies.SetStrategy("PartOfSpeech", strat); strat = ElementStrategy.CreateSingletonElement(); strat.IsAtomic = true; merger.MergeStrategies.SetStrategy("objsur", strat); XmlTestHelper.DoMerge(merger.MergeStrategies, merger.MergeSituation, commonAncestor, lee, matthew, new[] { "Lexicon/LexEntry/MorphoSyntaxAnalyses/MoStemMsa/PartOfSpeech/objsur[@guid='f92dbc59-e93f-4df2-b6bd-39a53e331201']" }, null, 1, new List <Type> { typeof(RemovedVsEditedElementConflict) }, 0, new List <Type>()); }