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"), }); }
/// <summary> /// Do a 3-file merge, placing the result over the "ours" file and returning an error status /// </summary> /// <remarks>Implementations can exit with an exception, which the caller will catch and deal with. /// The must not have any UI, no interaction with the user.</remarks> public void Do3WayMerge(MergeOrder mergeOrder) { Guard.AgainstNull(mergeOrder, "mergeOrder"); if (mergeOrder == null) { throw new ArgumentNullException("mergeOrder"); } var merger = new XmlMerger(mergeOrder.MergeSituation); SetupElementStrategies(merger); merger.EventListener = mergeOrder.EventListener; using (var oursXml = new HtmlFileForMerging(mergeOrder.pathToOurs)) using (var theirsXml = new HtmlFileForMerging(mergeOrder.pathToTheirs)) using (var ancestorXml = new HtmlFileForMerging(mergeOrder.pathToCommonAncestor)) { var result = merger.MergeFiles(oursXml.GetPathToXHtml(), theirsXml.GetPathToXHtml(), ancestorXml.GetPathToXHtml()); CarefullyWriteOutResultingXml(oursXml, result); //now convert back to html oursXml.SaveHtml(); } }
protected override void AddMergeStrategies(XmlMerger m) { 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")); }
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); }
/// <summary> /// Do a 3-file merge, placing the result over the "ours" file and returning an error status /// </summary> /// <remarks>Implementations can exit with an exception, which the caller will catch and deal with. /// The must not have any UI, no interaction with the user.</remarks> public void Do3WayMerge(MergeOrder mergeOrder) { if (mergeOrder == null) { throw new ArgumentNullException("mergeOrder"); } bool addedCollationAttr; PreMergeFile(mergeOrder, out addedCollationAttr); var merger = new XmlMerger(mergeOrder.MergeSituation); SetupElementStrategies(merger); merger.EventListener = mergeOrder.EventListener; XmlMergeService.RemoveAmbiguousChildNodes = true; var result = merger.MergeFiles(mergeOrder.pathToOurs, mergeOrder.pathToTheirs, mergeOrder.pathToCommonAncestor); using (var writer = XmlWriter.Create(mergeOrder.pathToOurs, CanonicalXmlSettings.CreateXmlWriterSettings())) { var readerSettings = CanonicalXmlSettings.CreateXmlReaderSettings(ConformanceLevel.Auto); readerSettings.XmlResolver = null; readerSettings.ProhibitDtd = false; using (var nodeReader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(result.MergedNode.OuterXml)), readerSettings)) { writer.WriteNode(nodeReader, false); } } }
public override void Run() { this.backupConfigGuid = this.BackupRepository.StoreFile((string)configuration.file); if (this.IsXml((string)configuration.file)) { XmlDocument target = new XmlDocument(); target.Load((string)configuration.file); XmlDocument source = new XmlDocument(); source.LoadXml((string)configuration.content); XmlMerger xmlMerger = new XmlMerger(target, new Dictionary <string, object>()); xmlMerger.ApplyChanges(source); target.Save((string)configuration.file); } else { JObject target = JObject.Parse(File.ReadAllText((string)this.configuration.file)); JObject source = JObject.Parse((string)configuration.content); JsonMergeSettings jsonMergeSettings = new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Replace }; target.Merge(source, jsonMergeSettings); File.WriteAllText((string)configuration.file, target.ToString()); } }
public void Run_WeAddedElement_ListenerGetsAdditionReport() { string ours = @"<a><b>new</b></a>"; string ancestor = @"<a/>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); TestCompare <XmlTextAddedReport>(merger, ours, ancestor, "//a"); }
public void Run_WeDeletedElement_ListenerGetsDeletionEditReport() { string ancestor = @"<a><b/></a>"; string ours = @"<a></a>"; XmlMerger merger = new XmlMerger(new NullMergeSituation()); TestCompare <XmlDeletionChangeReport>(merger, ours, ancestor, "//a"); }
/// <summary> /// Produce a string that represents the 3-way merger of the given three elements. /// </summary> public ChorusNotesAnnotationMergingStrategy(MergeOrder order) { _annotationMerger = new XmlMerger(order.MergeSituation) { EventListener = order.EventListener }; SetupElementStrategies(); }
/// <summary> /// Produce a string that represents the 3-way merger of the given three elements. /// </summary> public LiftEntryMergingStrategy(MergeOrder mergeOrder) { _entryMerger = new XmlMerger(mergeOrder.MergeSituation) { MergeStrategies = { ElementToMergeStrategyKeyMapper = new LiftElementToMergeStrategyKeyMapper() }, EventListener = mergeOrder.EventListener }; LiftElementStrategiesMethod.AddLiftElementStrategies(_entryMerger.MergeStrategies); }
public void FixtureSetup() { _mdc = MetadataCache.TestOnlyNewCache; var mergeOrder = new MergeOrder(null, null, null, new NullMergeSituation()) { EventListener = new ListenerForUnitTests() }; _merger = FieldWorksMergeServices.CreateXmlMergerForFieldWorksData(mergeOrder, _mdc); }
internal static XmlMerger CreateXmlMergerForFieldWorksData(MergeOrder mergeOrder, MetadataCache mdc) { var merger = new XmlMerger(mergeOrder.MergeSituation) { EventListener = mergeOrder.EventListener }; BootstrapSystem(mdc, merger); return(merger); }
public void Do3WayMerge(MetadataCache mdc, MergeOrder mergeOrder) { var merger = new XmlMerger(mergeOrder.MergeSituation) { EventListener = mergeOrder.EventListener }; CustomLayoutMergeStrategiesMethod.AddElementStrategies(merger.MergeStrategies); CustomLayoutMergeService.DoMerge(mergeOrder, merger); }
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"); }
public void TextElement_WeEdittedTheyDeleted_KeepAncestor() { string ancestor = @"<t>original</t>"; string ours = @"<t>mine</t>"; string theirs = @"<t></t>"; XmlMerger m = new XmlMerger(); MergeResult result = m.Merge(ours, theirs, ancestor, false); XmlTestHelper.AssertXPathMatchesExactlyOne(result.MergedNode, "t[text()='original']"); }
/// <summary> /// Constructor /// </summary> public LiftRangesMergingStrategy(MergeOrder mergeOrder) { _merger = new XmlMerger(mergeOrder.MergeSituation) { EventListener = mergeOrder.EventListener }; LiftBasicElementStrategiesMethod.AddLiftBasicElementStrategies(_merger.MergeStrategies); LiftRangesElementStrategiesMethod.AddLiftRangeElementStrategies(_merger.MergeStrategies); }
public override void TestSetup() { base.TestSetup(); Mdc.UpgradeToVersion(MetadataCache.MaximumModelVersion); var mergeOrder = new MergeOrder(null, null, null, new NullMergeSituation()) { EventListener = new ListenerForUnitTests() }; _merger = FieldWorksMergeServices.CreateXmlMergerForFieldWorksData(mergeOrder, Mdc); }
/// <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); } }
/// <summary> /// Gets the collection of element merge strategies. /// </summary> public MergeStrategies GetStrategies() { var merger = new XmlMerger(new MergeSituation(null, null, null, null, null, MergeOrder.ConflictHandlingModeChoices.WeWin)); var def = new ElementStrategy(true) { MergePartnerFinder = new FindByEqualityOfTree() }; merger.MergeStrategies.SetStrategy("def", def); return(merger.MergeStrategies); }
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); }
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"); }
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); }
public void XmlBothDeletionChangeReport_ReportsCorrectChangeWithoutCrashing() { // Setup var merger = new XmlMerger(new NullMergeSituation()); // Exercise var result = merger.Merge("<r></r>", "<r></r>", "<r><s><t>hello</t></s></r>"); // Verify Assert.That(result.Changes.Select(x => x.GetType()), Is.EqualTo(new[] { typeof(XmlBothDeletionChangeReport) })); Assert.That(result.Changes[0].ToString(), Is.EqualTo("Both deleted the <s>")); Assert.That(result.Changes[0].ActionLabel, Is.EqualTo("Deleted")); }
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_BothDeletedNonTextNodeHasChangeReport() { const string ancestor = @"<gloss lang='a'> <text id='me' /> </gloss>" ; const string ours = @"<gloss lang='a'> </gloss>" ; const string theirs = ours; var merger = new XmlMerger(new NullMergeSituation()); TestMergeWithChange <XmlBothDeletionChangeReport>(merger, ours, theirs, ancestor, "//gloss"); }
private static XmlMerger GetMerger(out ListenerForUnitTests listener, bool isAtomic) { var elementStrategy = new ElementStrategy(false) { IsAtomic = isAtomic }; var merger = new XmlMerger(new NullMergeSituation()); merger.MergeStrategies.SetStrategy("topatomic", elementStrategy); listener = new ListenerForUnitTests(); merger.EventListener = listener; return(merger); }
private static XmlMerger GetMerger(MergeSituation mergeSituation, out ListenerForUnitTests listener) { var elementStrategy = new ElementStrategy(false) { IsAtomic = true }; var merger = new XmlMerger(mergeSituation); merger.MergeStrategies.SetStrategy("topatomic", elementStrategy); listener = new ListenerForUnitTests(); merger.EventListener = listener; return(merger); }
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 void TestCompare <TChangeReport>(XmlMerger merger, string ours, string ancestors, string xpathToElementsToMerge) { var listener = new ListenerForUnitTests(); merger.EventListener = listener; var method = new MergeChildrenMethod(GetNode(ours, xpathToElementsToMerge), GetNode(ancestors, xpathToElementsToMerge), merger); method.Run(); listener.AssertExpectedConflictCount(0); listener.AssertExpectedChangesCount(1); Assert.AreEqual(typeof(TChangeReport), listener.Changes[0].GetType()); }
private static XmlNode DoMerge( string ancestorXml, string ourXml, string theirXml, MergeSituation mergeSituation, IMergeEventListener listener, out XmlNode ours, out XmlNode theirs) { var merger = new XmlMerger(mergeSituation) { EventListener = listener }; XmlNode ancestor; XmlNode ourParent; XmlTestHelper.CreateThreeNodes(ourXml, theirXml, ancestorXml, out ours, out ourParent, out theirs, out ancestor); ImmutableElementMergeService.DoMerge(merger, ourParent, ref ours, theirs, ancestor); return(ours); }
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); }