private static void SetupElementStrategies(XmlMerger merger)
        {
            merger.MergeStrategies.ElementToMergeStrategyKeyMapper = new BloomElementToStrategyKeyMapper();

            merger.MergeStrategies.SetStrategy("html", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("head", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("body", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("DataDiv", new ElementStrategy(true)
            {
                IsAtomic           = false,
                OrderIsRelevant    = false,
                MergePartnerFinder = new FindByKeyAttribute("id"),                 //yes, it's a singleton of sorts, but by the id, not the tag
            });

            merger.MergeStrategies.SetStrategy("BookDataItem", new ElementStrategy(true)
            {
                IsAtomic           = true,
                OrderIsRelevant    = false,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string>(new string[] { "data-book", "lang" }))
            });

            merger.MergeStrategies.SetStrategy("PageDiv", new ElementStrategy(true)
            {
                IsAtomic           = true,                                                                                               //we're not trying to merge inside pages
                MergePartnerFinder = new FindByKeyAttribute("id"),
            });
        }
Ejemplo n.º 2
0
        private static ElementStrategy CreateSingletonElementStrategy()
        {
            var result = ElementStrategy.CreateSingletonElement();

            result.ContextDescriptorGenerator = ContextGen;
            return(result);
        }
Ejemplo n.º 3
0
 public void TestSetup()
 {
     _mergeStrategies = new MergeStrategies();
     _mergeStrategies.ElementStrategies.Add("a", ElementStrategy.CreateSingletonElement());
     _mergeStrategies.ElementStrategies.Add("b", ElementStrategy.CreateSingletonElement());
     _mergeStrategies.ElementStrategies.Add("c", ElementStrategy.CreateSingletonElement());
     _mergeStrategies.ElementStrategies.Add("d", ElementStrategy.CreateSingletonElement());
 }
        public void Run_WeEditedTextElementInsideSingleton_ListenerGetsTextEditReport()
        {
            string ours     = @"<a><b>new</b></a>";
            string ancestor = @"<a><b>old</b></a>";

            XmlMerger merger = new XmlMerger(new NullMergeSituation());

            merger.MergeStrategies.SetStrategy("b", ElementStrategy.CreateSingletonElement());
            TestCompare <XmlTextChangedReport>(merger, ours, ancestor, "//a");
        }
Ejemplo n.º 5
0
        internal static void AddElementStrategies(MergeStrategies mergeStrategies)
        {
            // Document root.
            mergeStrategies.SetStrategy("LayoutInventory", ElementStrategy.CreateSingletonElement());

            #region 'layoutType' and children.
            mergeStrategies.SetStrategy("layoutType", ElementStrategy.CreateSingletonElement());

            var elStrat = new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "class", "layout"
                }),
                NumberOfChildren           = NumberOfChildrenAllowed.Zero,
                IsAtomic                   = true,
                ContextDescriptorGenerator = new FieldWorkCustomLayoutContextGenerator()
            };
            mergeStrategies.SetStrategy("configure", elStrat);
            #endregion 'layoutType' and children.

            #region 'layout' and children.
            elStrat = new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "class", "type", "name"
                }),
                ContextDescriptorGenerator = new FieldWorkCustomLayoutContextGenerator()
            };
            mergeStrategies.SetStrategy("layout", elStrat);

            elStrat = new ElementStrategy(true)
            {
                MergePartnerFinder = new FindByKeyAttributeInList("ref"),
                IsAtomic           = true
            };
            mergeStrategies.SetStrategy("part", elStrat);

            elStrat = new ElementStrategy(true)
            {
                //MergePartnerFinder = new FindByMultipleKeyAttributes(new List<string> { "class", "fieldType", "restrictions" }),
                MergePartnerFinder = new FindByKeyAttributeInList("combinedkey"),
                IsAtomic           = true
            };
            mergeStrategies.SetStrategy("generate", elStrat);

            elStrat = new ElementStrategy(true)
            {
                MergePartnerFinder = new FindByKeyAttributeInList("name"),
                IsAtomic           = true,
                NumberOfChildren   = NumberOfChildrenAllowed.Zero
            };
            mergeStrategies.SetStrategy("sublayout", elStrat);
            #endregion 'layout' and children.
        }
Ejemplo n.º 6
0
        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)
            });
        }
Ejemplo n.º 7
0
        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");
        }
Ejemplo n.º 8
0
        public void Do3WayMerge(MetadataCache mdc, MergeOrder mergeOrder)
        {
            var merger = new XmlMerger(mergeOrder.MergeSituation)
            {
                EventListener = mergeOrder.EventListener
            };
            var rootStrategy = ElementStrategy.CreateSingletonElement();

            rootStrategy.IsAtomic = true;
            merger.MergeStrategies.SetStrategy("DictionaryConfiguration", rootStrategy);
            var mergeResults = merger.MergeFiles(mergeOrder.pathToOurs, mergeOrder.pathToTheirs, mergeOrder.pathToCommonAncestor);

            // Write merged data
            File.WriteAllText(mergeOrder.pathToOurs, mergeResults.MergedNode.OuterXml, Encoding.UTF8);
        }
Ejemplo n.º 9
0
        internal static void SetupElementStrategies(XmlMerger merger)
        {
            // See: Palaso repo: SIL.LexiconUtils\UserLexiconSettingsDataMapper.cs
            var strategy = ElementStrategy.CreateSingletonElement();

            strategy.ContextDescriptorGenerator = new UserLexiconSettingsContextGenerator();
            merger.MergeStrategies.SetStrategy("UserLexiconSettings", strategy);
            // Child elements of lexicon project settings root.

            merger.MergeStrategies.SetStrategy("WritingSystems", ElementStrategy.CreateSingletonElement());
            // Child elements of "WritingSystems".

            merger.MergeStrategies.SetStrategy("WritingSystem", new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByKeyAttribute("id")
            }
                                               );
            merger.MergeStrategies.SetStrategy("LocalKeyboard", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("KnownKeyboards", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("DefaultFontName", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("DefaultFontSize", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("IsGraphiteEnabled", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
        }
Ejemplo n.º 10
0
        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");
        }
Ejemplo n.º 11
0
        public void Run_WeRemoved_TheyEdited_TextNode_GetConflictReport()
        {
            string ancestor = @"<gloss lang='a'>
									<text>original</text>
								 </gloss>"                                ;
            string ours     = @"<gloss lang='a'>
							</gloss>"                            ;

            string theirs = @"<gloss lang='a'>
									<text>theirGloss</text>
								 </gloss>"                                ;

            XmlMerger merger = new XmlMerger(new NullMergeSituation());

            //without this stategy, we'd get an AmbiguousInsertConflict
            merger.MergeStrategies.SetStrategy("text", ElementStrategy.CreateSingletonElement());

            TestMerge <XmlTextRemovedVsEditConflict>(merger, ours, theirs, ancestor, "//gloss");
        }
Ejemplo n.º 12
0
        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");
        }
        private static void SetupElementStrategies(XmlMerger merger)
        {
            merger.MergeStrategies.ElementToMergeStrategyKeyMapper = new BloomElementToStrategyKeyMapper();

            merger.MergeStrategies.SetStrategy("html", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("head", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("body", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("DataDiv", new ElementStrategy(true)
            {
                IsAtomic           = false,
                OrderIsRelevant    = false,
                MergePartnerFinder = new FindByKeyAttribute("id"),                 //yes, it's a singleton of sorts, but by the id, not the tag
            });
            merger.MergeStrategies.SetStrategy("BookDataItem", new ElementStrategy(true)
            {
                IsAtomic           = true,
                OrderIsRelevant    = false,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string>(new string[] { "data-book", "lang" }))
            });
            merger.MergeStrategies.SetStrategy("PageDiv", new ElementStrategy(true)
            {
                IsAtomic                   = false,
                MergePartnerFinder         = new FindByKeyAttribute("id"),
                ContextDescriptorGenerator = new BloomPageContextGenerator()
            });
            merger.MergeStrategies.SetStrategy("TranslationGroup", new ElementStrategy(true)
            {
                IsAtomic                   = false,
                MergePartnerFinder         = new FindByKeyAttributeInList("class"),
                ContextDescriptorGenerator = new BloomPageContextGenerator()
            });
            merger.MergeStrategies.SetStrategy("LangDiv", new ElementStrategy(true)
            {
                IsAtomic                   = true,
                MergePartnerFinder         = new FindByKeyAttribute("lang"),
                ContextDescriptorGenerator = new BloomPageContextGenerator()
            });
        }
Ejemplo n.º 14
0
        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");
        }
Ejemplo n.º 15
0
        public void ElementStrategy_CreateSingletonElement_Has_FindFirstElementWithSameName_Finder()
        {
            var elementStrategy = ElementStrategy.CreateSingletonElement();

            Assert.IsInstanceOf <FindFirstElementWithSameName>(elementStrategy.MergePartnerFinder);
        }
Ejemplo n.º 16
0
        internal static void SetupElementStrategies(XmlMerger merger)
        {
            merger.MergeStrategies.ElementToMergeStrategyKeyMapper = new LdmlElementToMergeStrategyKeyMapper();

            // See: Palaso repo: SIL.WritingSystems\LdmlDataMapper.cs
            var strategy = ElementStrategy.CreateSingletonElement();

            strategy.ContextDescriptorGenerator = new LdmlContextGenerator();
            merger.MergeStrategies.SetStrategy("ldml", strategy);
            // Child elements of ldml root.

            merger.MergeStrategies.SetStrategy("identity", ElementStrategy.CreateSingletonElement());
            // Child elements of "identity".
            merger.MergeStrategies.SetStrategy("version", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("generation", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("language", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("script", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("territory", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("variant", ElementStrategy.CreateSingletonElement());

            // sil:special can occur several times throughout the file
            merger.MergeStrategies.SetStrategy("special_xmlns:sil", new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByMatchingAttributeNames(new HashSet <string> {
                    "xmlns:sil"
                })
            });
            merger.MergeStrategies.SetStrategy("sil:identity", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("localeDisplayNames", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("layout", ElementStrategy.CreateSingletonElement());
            // Child element of "layout".
            merger.MergeStrategies.SetStrategy("orientation", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            });

            merger.MergeStrategies.SetStrategy("contextTransforms", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("characters", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            });

            merger.MergeStrategies.SetStrategy("delimiters", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            });

            merger.MergeStrategies.SetStrategy("dates", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("numbers", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            });

            merger.MergeStrategies.SetStrategy("units", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("listPatterns", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("collations", ElementStrategy.CreateSingletonElement());
            // Child element of collations
            strategy = new ElementStrategy(false)
            {
                IsAtomic           = true,       // I (RBR) think it would be suicidal to try and merge this element.
                MergePartnerFinder = new FindByKeyAttribute("type")
            };
            merger.MergeStrategies.SetStrategy("collation", strategy);
            // Child of 'collation' element (They exist, but we don't care what they are, as long as the parent is 'atomic'.

            merger.MergeStrategies.SetStrategy("posix", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("segmentations", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("rbnf", ElementStrategy.CreateSingletonElement());

            merger.MergeStrategies.SetStrategy("metadata", ElementStrategy.CreateSingletonElement());


            // See: Palaso repo: SIL.WritingSystems\LdmlDataMapper.cs
            // There currently are up to three 'special' child elements of the 'ldml' root element.
            // Special "xmlns:palaso" attr
            strategy = new ElementStrategy(false)
            {
                IsAtomic           = true,       // May not be needed...
                MergePartnerFinder = new FindByMatchingAttributeNames(new HashSet <string> {
                    "xmlns:palaso"
                })
            };
            merger.MergeStrategies.SetStrategy("special_xmlns:palaso", strategy);

            /* Not needed, as long as the parent is 'atomic'.
             * // Children of 'special' xmlns:palaso
             * // palaso:abbreviation
             * merger.MergeStrategies.SetStrategy("palaso:abbreviation", ElementStrategy.CreateSingletonElement());
             * // palaso:defaultFontFamily
             * merger.MergeStrategies.SetStrategy("palaso:defaultFontFamily", ElementStrategy.CreateSingletonElement());
             * // palaso:defaultFontSize
             * merger.MergeStrategies.SetStrategy("palaso:defaultFontSize", ElementStrategy.CreateSingletonElement());
             * // palaso:defaultKeyboard
             * merger.MergeStrategies.SetStrategy("palaso:defaultKeyboard", ElementStrategy.CreateSingletonElement());
             * // palaso:isLegacyEncoded
             * merger.MergeStrategies.SetStrategy("palaso:isLegacyEncoded", ElementStrategy.CreateSingletonElement());
             * // palaso:languageName
             * merger.MergeStrategies.SetStrategy("palaso:languageName", ElementStrategy.CreateSingletonElement());
             * // palaso:spellCheckingId
             * merger.MergeStrategies.SetStrategy("palaso:spellCheckingId", ElementStrategy.CreateSingletonElement());
             * // palaso:version
             * merger.MergeStrategies.SetStrategy("palaso:version", ElementStrategy.CreateSingletonElement());
             */

            // See: Palaso repo: SIL.WritingSystems\LdmlDataMapper.cs
            // special "xmlns:palaso2" attr: want to merge knownKeyboards child. So the root element is not atomic.
            strategy = new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByMatchingAttributeNames(new HashSet <string> {
                    "xmlns:palaso2"
                })
            };
            merger.MergeStrategies.SetStrategy("special_xmlns:palaso2", strategy);
            // Children of 'strategy' xmlns:palaso2
            // palaso2:knownKeyboards:
            merger.MergeStrategies.SetStrategy("palaso2:knownKeyboards", ElementStrategy.CreateSingletonElement());
            // Multiple children of "palaso2:knownKeyboards" element
            strategy = new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "layout", "locale"
                })
            };
            merger.MergeStrategies.SetStrategy("palaso2:keyboard", strategy);
            merger.MergeStrategies.SetStrategy("palaso2:version", ElementStrategy.CreateSingletonElement());

            // Special "xmlns:fw" attr (See FW source file: Src\Common\CoreImpl\PalasoWritingSystemManager.cs
            strategy = new ElementStrategy(false)
            {
                IsAtomic           = true,       // Really is needed. At least it is for some child elements.
                MergePartnerFinder = new FindByMatchingAttributeNames(new HashSet <string> {
                    "xmlns:fw"
                })
            };
            merger.MergeStrategies.SetStrategy("special_xmlns:fw", strategy);

            /* Not needed, as long as the parent is 'atomic'.
             * // Children for 'special' xmlns:fw
             * merger.MergeStrategies.SetStrategy("fw:defaultFontFeatures", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:graphiteEnabled", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:legacyMapping", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:matchedPairs", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:punctuationPatterns", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:quotationMarks", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:regionName", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:scriptName", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:validChars", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:variantName", ElementStrategy.CreateSingletonElement());
             * merger.MergeStrategies.SetStrategy("fw:windowsLCID", ElementStrategy.CreateSingletonElement());
             */

            // Children for top level 'special' xmlns:sil
            merger.MergeStrategies.SetStrategy("sil:external-resources", ElementStrategy.CreateSingletonElement());
            merger.MergeStrategies.SetStrategy("sil:kbd", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "id", "alt"
                })
            }
                                               );
            merger.MergeStrategies.SetStrategy("sil:font", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "name", "alt"
                })
            }
                                               );
            merger.MergeStrategies.SetStrategy("sil:spellcheck", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "type", "alt"
                })
            }
                                               );
            merger.MergeStrategies.SetStrategy("sil:transform", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List <string> {
                    "from", "to", "type", "direction", "function", "alt"
                })
            }
                                               );
        }
        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>());
        }
        internal static void SetupElementStrategies(XmlMerger merger)
        {
            // See: Palaso repo: SIL.LexiconUtils\ProjectLexiconSettingsDataMapper.cs
            var strategy = ElementStrategy.CreateSingletonElement();

            strategy.ContextDescriptorGenerator = new ProjectLexiconSettingsContextGenerator();
            merger.MergeStrategies.SetStrategy("ProjectLexiconSettings", strategy);
            // Child elements of lexicon project settings root.

            merger.MergeStrategies.SetStrategy("WritingSystems", ElementStrategy.CreateSingletonElement());
            // Child elements of "WritingSystems".

            merger.MergeStrategies.SetStrategy("WritingSystem", new ElementStrategy(false)
            {
                MergePartnerFinder = new FindByKeyAttribute("id")
            }
                                               );
            merger.MergeStrategies.SetStrategy("Abbreviation", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("LanguageName", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("ScriptName", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("RegionName", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("SpellCheckingId", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("LegacyMapping", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("Keyboard", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
            merger.MergeStrategies.SetStrategy("SystemCollation", new ElementStrategy(false)
            {
                IsAtomic           = true,
                MergePartnerFinder = new FindFirstElementWithSameName()
            }
                                               );
        }