예제 #1
0
 /// <summary>
 /// Return the ElementStrategy instance for the given <param name="element"/>, or a default instance set up like this:
 /// ElementStrategy def = new ElementStrategy(true);//review: this says the default is to consider order relevant
 /// def.MergePartnerFinder = new FindByEqualityOfTree();
 /// </summary>
 public ElementStrategy GetElementStrategy(XmlNode element)
 {
     var def = new ElementStrategy(true)
               	{
               		MergePartnerFinder = new FindByEqualityOfTree()
               	};
     return def;
 }
예제 #2
0
        public static ElementStrategy CreateForKeyedElementInList(string keyAttributeName)
        {
            var strategy = new ElementStrategy(true)
            {
                MergePartnerFinder = new FindByKeyAttributeInList(keyAttributeName)
            };

            return(strategy);
        }
예제 #3
0
        /// <summary>
        /// Declare that there can only be a single element with this name in a list of children
        /// </summary>
        public static ElementStrategy CreateSingletonElement()
        {
            var strategy = new ElementStrategy(false)
            {
                MergePartnerFinder = new FindFirstElementWithSameName()
            };

            return(strategy);
        }
예제 #4
0
        /// <summary>
        /// Return the ElementStrategy instance for the given <param name="element"/>, or a default instance set up like this:
        /// ElementStrategy def = new ElementStrategy(true);//review: this says the default is to consider order relevant
        /// def.MergePartnerFinder = new FindByEqualityOfTree();
        /// </summary>
        public ElementStrategy GetElementStrategy(XmlNode element)
        {
            var def = new ElementStrategy(true)
            {
                MergePartnerFinder = new FindByEqualityOfTree()
            };

            return(def);
        }
예제 #5
0
        public static ElementStrategy CreateForKeyedElement(string keyAttributeName, bool orderIsRelevant)
        {
            var strategy = new ElementStrategy(orderIsRelevant)
            {
                MergePartnerFinder = new FindByKeyAttribute(keyAttributeName)
            };

            return(strategy);
        }
 internal static ElementStrategy AddKeyedElementType(MergeStrategies mergeStrategies, string name, string attribute, bool orderOfTheseIsRelevant)
 {
     var strategy = new ElementStrategy(orderOfTheseIsRelevant)
                     {
                         MergePartnerFinder = new FindByKeyAttribute(attribute)
                     };
     mergeStrategies.SetStrategy(name, strategy);
     return strategy;
 }
예제 #7
0
 /// <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;
 }
		private static ElementStrategy MakeClassStrategy(FieldWorkObjectContextGenerator descriptor, MergeStrategies strategies)
		{
			var classStrat = new ElementStrategy(false)
			{
				MergePartnerFinder = GuidKey,
				ContextDescriptorGenerator = descriptor,
				IsAtomic = false
			};
			descriptor.MergeStrategies = strategies;
			return classStrat;
		}
예제 #9
0
        /// <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 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.
		}
예제 #11
0
        public MergeStrategies()
        {
            ElementStrategies = new Dictionary <string, ElementStrategy>();
            ElementStrategy s = new ElementStrategy(true);            //review: this says the default is to consider order relevant

            s.MergePartnerFinder = new FindTextDumb();
            SetStrategy("_" + XmlNodeType.Text, s);

            ElementStrategy def = new ElementStrategy(true);            //review: this says the default is to consider order relevant

            def.MergePartnerFinder = new FindByEqualityOfTree();
            SetStrategy("_defaultElement", def);

            ElementToMergeStrategyKeyMapper = new DefaultElementToMergeStrategyKeyMapper();
        }
예제 #12
0
		/// <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);
			}
		}
예제 #13
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" })
                }
            );
        }
예제 #14
0
        public MergeStrategies()
        {
            ElementStrategies = new Dictionary<string, ElementStrategy>();
            ElementStrategy s = new ElementStrategy(true);//review: this says the default is to consider order relevant
            s.MergePartnerFinder = new FindTextDumb();
            SetStrategy("_"+XmlNodeType.Text, s);

            ElementStrategy def = new ElementStrategy(true);//review: this says the default is to consider order relevant
            def.MergePartnerFinder = new FindByEqualityOfTree();
            SetStrategy("_defaultElement", def);

            ElementToMergeStrategyKeyMapper = new DefaultElementToMergeStrategyKeyMapper();
        }
 public void UsingWith_NumberOfChildrenAllowed_ZeroOrMore_Throws()
 {
     var strategy = new ElementStrategy(false)
                     {
                         NumberOfChildren = NumberOfChildrenAllowed.ZeroOrMore
                     };
     var doc = new XmlDocument();
     var parent = doc.CreateNode(XmlNodeType.Element, "somenode", null);
     Assert.Throws<InvalidOperationException>(() => MergeLimitedChildrenService.Run(new XmlMerger(new NullMergeSituation()), strategy, ref parent, parent, parent));
 }
 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;
 }
예제 #17
0
 /// <summary>
 /// Declare that there can only be a single element with this name in a list of children
 /// </summary>
 public static ElementStrategy CreateSingletonElement()
 {
     var strategy = new ElementStrategy(false)
         {
             MergePartnerFinder = new FindFirstElementWithSameName()
         };
     return strategy;
 }
예제 #18
0
 private static void AddTranslationStrategy(MergeStrategies mergeStrategies)
 {
     var strategy = new ElementStrategy(false)
                     {
                         MergePartnerFinder = new OptionalKeyAttrFinder("type", new FormMatchingFinder())
                     };
     mergeStrategies.SetStrategy("translation", strategy);
 }
 public void CanSetToTrue()
 {
     var elementStrategy = new ElementStrategy(false)
         {
             IsAtomic = true
         };
     Assert.IsTrue(elementStrategy.IsAtomic);
 }
예제 #20
0
 public void PreMergeCalledBeforeMerging()
 {
     string red = @"<a/>";
     string ancestor = red;
     string blue = @"<a>
                         <b key='one'>
                             <c>first</c>
                         </b>
                     </a>";
     var specialMergeStrategies = new Dictionary<string, ElementStrategy>();
     var elementStrat = new ElementStrategy(true)
         {
             Premerger = new SillyPremerger()
         };
     specialMergeStrategies["a"] = elementStrat;
     CheckOneWay(red, blue, ancestor, new NullMergeSituation(), specialMergeStrategies, (Action<string, ElementStrategy>)null,
         "a[@silly='nonsense']/b[@key='one']/c[text()='first']");
 }
예제 #21
0
        internal static void AddLiftElementStrategies(MergeStrategies mergeStrategies)
        {
            LiftBasicElementStrategiesMethod.AddLiftBasicElementStrategies(mergeStrategies);
            LiftRangesElementStrategiesMethod.AddLiftRangeElementStrategies(mergeStrategies);

            #region Header Elements

            //enhance: don't currently have a way of limiting etymology/form to a single instance but not multitext/form

            // ******************************* <lift> **************************************************
            // Added to complete the whole file, but it gets no ElementStrategy.
            // <lift
            //		version [Required, (string?)]
            //		producer [Optional, string]
            //		<header> [Optional, header]
            //		<entry> [Optional, Multiple, Entry]
            // </lift>
            // ******************************* <lift> **************************************************

            // ******************************* <header> **************************************************
            // <header
            var elementStrategy = AddSingletonElementType(mergeStrategies, "header");
            elementStrategy.ContextDescriptorGenerator = new LiftHeaderContextGenerator();
            //		<description> [Optional, multitext] NAME OVERRIDE (Declared in [LiftBasicElementStrategiesMethod], as it is shared here and in the lift-ranges file.)
            //		<ranges> [Optional, ranges]
            elementStrategy = AddSingletonElementType(mergeStrategies, "ranges");
            elementStrategy.OrderIsRelevant = false;
            //		<fields> [Optional, field-defns] NAME OVERRIDE
            elementStrategy = AddSingletonElementType(mergeStrategies, "fields");
            elementStrategy.OrderIsRelevant = false;
            // </header>
            // ******************************* </header> **************************************************

            // ******************************* <ranges> **************************************************
            // <ranges
            //		<range> [Optional, Multiple, range-ref] NAME OVERRIDE
            //	NB: Done in LiftRangesElementStrategiesMethod
            // </ranges>
            // ******************************* </ranges> **************************************************

            // ******************************* <field-defns> **************************************************
            // <field-defns
            //		<field> [Optional, Multiple, field-defn] NAME OVERRIDE
            // </field-defns>
            // ******************************* </field-defns> **************************************************

            // ******************************* <field-defn> **************************************************
            // <field-defn> element never occurs in the wild (0.13), as it always gets a name change to <field>.
            // <field-defn (aka <field> in 0.13)
            //		tag [Required, key]
            // !!!!!!!!! HACK ALERT !!!!!!!!!
            LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "headerfield", "tag", false);
            // !!!!!!!!! END HACK ALERT !!!!!!!!!
            //		<form> [optional, multiple]
            // </field-defn>
            // ******************************* </field-defn> **************************************************

            #endregion #region Header Elements

            #region Entry Elements

            // ******************************* <extensible> **************************************************
            // Notes: This is only be a bundle of attrs and content others can use, rather than an actual element in the file.
            // <extensible
            //		dateCreated [Optional, datetime] // attr in UML
            //		dateModified [Optional, datetime] // attr in UML
            //		<field> [Optional, Multiple, field]
            //		<trait> [Optional, Multiple, trait] // NB: sig changed in text to 'flag', but 'trait' in UML.
            //		<annotation> [Optional, Multiple, annotation]
            // </extensible>
            // It is 'abstract', so no element strategy is needed.
            // ******************************* </extensible> **************************************************

            // ******************************* <field> **************************************************
            // Technically part of Base, but I don't know why, as the <field> elements appear in entries (or maybe senses).
            // Formal inheritance from <multitext>, and partial from <extensible> (all but <field>).
            // Observation: <field> inherits everything, except its 'type' attribute.
            // <field
            //		type [Required, sig=key]
            // !!!!!!!!! HACK ALERT !!!!!!!!!
            elementStrategy = LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "mainfield", "type", false);
            // !!!!!!!!! END HACK ALERT !!!!!!!!!
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<trait> [Optional, Multiple, trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            // </field>
            // ******************************* </field> **************************************************

            // ******************************* <trait> **************************************************
            // Notes: A trait is simply a reference to a single range-element
            //		in a range. It can be used to give the dialect for a variant or the status of an entry.
            //		The semantics of a trait in a particular context is given by the parent object and also by the range
            //		and range-element being referred to. Where no range is linked the name is informal or resolved by name.
            // <trait
            //		name [Required, sig=key]
            //		value [Required, sig=key]
            elementStrategy = new ElementStrategy(false)
                                {
                                    // Need both keys to find the match.
                                    MergePartnerFinder = new FindByMultipleKeyAttributes(new List<string> { "name", "value" })
                                };
            mergeStrategies.SetStrategy("trait", elementStrategy);
            //		id [Optional, sig=key] // Note: Gives the particular trait an identifier such that it can be referenced by a sibling element.
            //									The id key only needs to be unique within the parent element, although globale keys may be used.
            //									There is no requirement that the key keeps its value across different versions of the file.
            //		<annotation /> [Optional, Multiple, sig=annotation]
            // </trait>
            // ******************************* </trait> **************************************************

            // ******************************* <note> **************************************************
            // <note
            //		type [Optional, sig=key] There is only one note with a given type in any parent element.
            //									Thus translations of the note are held as different forms of the one note.
            elementStrategy = new ElementStrategy(false)
                                {
                                    MergePartnerFinder = new OptionalKeyAttrFinder("type", new FormMatchingFinder())
                                };
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            mergeStrategies.SetStrategy("note", elementStrategy);
            // </note>
            // ******************************* </note> **************************************************

            // ******************************* <relation> **************************************************
            // <relation
            //		type [Required, sig=key]
            //		ref [Required, sig=refid]
            elementStrategy = new ElementStrategy(false)
                                {
                                    // Need both keys to find this puppy's match.
                                    MergePartnerFinder = new FindByMultipleKeyAttributes(new List<string> { "type", "ref" })
                                };
            mergeStrategies.SetStrategy("relation", elementStrategy);
            //		order [Optional, sig=int]
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<usage> [Optional, sig=multitext]
            AddSingletonElementType(mergeStrategies, "usage");
            // </relation>
            // ******************************* </relation> **************************************************

            #region Entry

            // ******************************* <entry> **************************************************
            // <entry
            //		id [Optional, refid] This gives a unique identifier to this Entry. Notice that this is unique across all Entrys and **all Senses**.
            elementStrategy = LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "entry", "id", false);
            elementStrategy.ContextDescriptorGenerator = new LexEntryContextGenerator();
            //		order [Optional, int]
            //		guid [Optional, string]
            //		dateDeleted [Optional, datetime]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateDeleted"); // One might think it is immutable, but it might not be true.
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<lexical-unit> [Optional, multitext]
            AddSingletonElementType(mergeStrategies, "lexical-unit");
            //		<citation> [Optional, multitext]
            AddSingletonElementType(mergeStrategies, "citation");
            //		<pronunciation> [Optional, Multiple, phonetic] NAME OVERRIDE
            AddPronunciationStrategy(mergeStrategies);
            //		<variant> [Optional, Multiple, variant] dealt with below
            //		<sense> [Optional, Multiple, Sense]
            //		<note> [Optional, Multiple, note]
            //		<relation> [Optional, Multiple, relation]
            //		<etymology> [Optional, Multiple, etymology]
            // </entry>
            // ******************************* </entry> **************************************************

            // ******************************* <variant> **************************************************
            // <variant
            //		ref [Optional, refid] NOTE: Doc: refentry, UML: refid, so go with refid, since there is nothing called refentry. Gives the variation as a reference to another entry or sense rather than specifying the form
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            //		<pronunciation> [Optional, Multiple, sig=phonetic]
            //		<relation> [Optional, Multiple, sig=relation]
            // </variant>
            AddVariantStrategy(mergeStrategies);
            // ******************************* </variant> **************************************************

            // ******************************* <phonetic> **************************************************
            // NB: Element name changed to <pronunciation>
            // <phonetic
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>] ignored in phonetic strategy
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            //		<media> [Optional, Multiple, sig=URLRef] NAME OVERRIDE
            // Not ever in lift file, as <pronunciation> wraps it. AddPhoneticStrategy(mergeStrategies);
            LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "media", "href", false);
            // </phonetic>
            // ******************************* </phonetic> **************************************************

            // ******************************* <etymology> **************************************************
            // <etymology
            //		type [Required, sig=key]
            //		source [Required, sig=key] // UML has 'key', doc has 'string'. Go with key
            elementStrategy = new ElementStrategy(false)
                                {
                                    // SteveMc says to use them both.
                                    // Need both keys to find the match.
                                    MergePartnerFinder = new FindByMultipleKeyAttributes(new List<string> { "type", "source" })
                                };
            mergeStrategies.SetStrategy("etymology", elementStrategy);
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<gloss> [Optional, Multiple, sig=form]
            //		<form> [Required, sig=form] // UML has Optional
            // </etymology>
            // ******************************* </etymology> **************************************************

            #endregion Entry

            #region Sense

            // ******************************* <sense> **************************************************
            // <sense
            //		id [Optional, refid] The id is unique across all Senses in the lexicon and all Entries as well.
            elementStrategy = LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "sense", "id", true);// main sense and nested senses, according to doc
            //		order [Optional int]
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            elementStrategy.AttributesToIgnoreForMerging.Add("dateModified");
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<grammatical-info> [Optional, grammi] grammi? Better go with grammatical-info. (Added below)
            //		<gloss> [Optional, Multiple, form]
            LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "gloss", "lang", false);
            //		<definition> [Optional, multitext]
            AddSingletonElementType(mergeStrategies, "definition");
            //		<relation> [Optional, Multiple, relation] (Added below)
            //		<note> [Optional, Multiple, note] (Added below)
            //		<example> [Optional, Multiple, example] (Must use default element strategy, or some other hand-made one.)
            //		<reversal> [Optional, Multiple, reversal] (Added below)
            //		<illustration> [Optional, Multiple, URLref] NAME OVERRIDE
            LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "illustration", "href", false);
            //		<subsense> [Optional, Multiple, sense] NAME OVERRIDE
            LiftBasicElementStrategiesMethod.AddKeyedElementType(mergeStrategies, "subsense", "id", true); // nested sense in a <sense>, according to rng
            // </sense>
            // ******************************* </sense> **************************************************

            // ******************************* <reversal> **************************************************
            // <reversal
            //		type [Optional, sig=key]
            AddReversalStrategy(mergeStrategies);
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            //		<main> [Optional, sig=reversal] NAME OVERRIDE
            AddSingletonElementType(mergeStrategies, "main");
            //		<grammatical-info> [Optional, sig=grammatical-info] (Added elsewhere)
            // </reversal>
            // ******************************* </reversal> **************************************************

            // ******************************* <grammatical-info> **************************************************
            // <grammatical-info
            //		value [Required, sig=key] The part of speech tag into the grammatical-info range.
            //		<trait> {Optional, Multiple, sig=trait] Allows grammatical information to have attributes.
            // </grammatical-info>
            // Sense and reversal have this as Optional, so singleton will do, while keyed is more future-safe.
            // It may bad to use a key, since if a user changes the 'value', then we'd get two of them.
            AddSingletonElementType(mergeStrategies, "grammatical-info");
            // ******************************* </grammatical-info> **************************************************

            // ******************************* <example> **************************************************
            // <example
            AddExampleSentenceStrategy(mergeStrategies);
            // 'dateModified' is ignored in AddExampleSentenceStrategy
            //		source [Optional, key] // Not suitable for keyed el strat.
            //		dateCreated [Optional, sig=datetime, inherited from <extensible>]
            //		dateModified [Optional, sig=datetime, inherited from <extensible>]
            //		<field> [Optional, Multiple, sig=field, inherited from <extensible>]
            //		<trait> [Optional, Multiple, sig=trait, inherited from <extensible>]
            //		<annotation> [Optional, Multiple, sig=annotation, inherited from <extensible>]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            //		<translation> [Optional, Multiple, sig=translation]
            // </example>
            // ******************************* </example> **************************************************

            // ******************************* <translation> **************************************************
            // A translation is simply a multitext with an optional translation type attribute.
            // <translation
            //		type [Optional, key]
            AddTranslationStrategy(mergeStrategies);
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            // </translation>
            // ******************************* </translation> **************************************************

            #endregion Sense

            #endregion End Entry Elements
        }
예제 #22
0
 public void SetStrategy(string key, ElementStrategy strategy)
 {
     ElementStrategies[key] = strategy;
     _elementStrategyKeys.Add(key);
 }
예제 #23
0
 public void SetStrategy(string key, ElementStrategy strategy)
 {
     ElementStrategies[key] = strategy;
     _elementStrategyKeys.Add(key);
 }
        public void UsingWith_NumberOfChildrenAllowed_Zero_ThrowsWhenTheirsHasChildNode()
        {
            var strategy = new ElementStrategy(false)
            {
                NumberOfChildren = NumberOfChildrenAllowed.Zero
            };
            var doc = new XmlDocument();
            var theirs = doc.CreateNode(XmlNodeType.Element, "somenode", null);
            var theirChild = doc.CreateNode(XmlNodeType.Element, "child", null);
            theirs.AppendChild(theirChild);

            var ours = doc.CreateNode(XmlNodeType.Element, "somenode", null);
            var ancestor = doc.CreateNode(XmlNodeType.Element, "somenode", null);

            Assert.Throws<InvalidOperationException>(() => MergeLimitedChildrenService.Run(new XmlMerger(new NullMergeSituation()), strategy, ref ours, theirs, ancestor));
        }
예제 #25
0
        public static void Run(XmlMerger merger, ElementStrategy strategy, ref XmlNode ours, XmlNode theirs, XmlNode ancestor)
        {
// All routes tested in this method.
            Guard.AgainstNull(merger, "merger");             // Route tested.
            Guard.AgainstNull(strategy, "strategy");         // Route tested.
            if (ours == null && theirs == null && ancestor == null)
            {
                throw new ArgumentNullException();                 // Route tested.
            }
            if (XmlUtilities.IsTextLevel(ours, theirs, ancestor))
            {
                // Route tested.
                new MergeTextNodesMethod(merger, merger.MergeStrategies.GetElementStrategy(ours ?? theirs ?? ancestor),
                                         new HashSet <XmlNode>(),
                                         ref ours, new List <XmlNode>(),
                                         theirs, new List <XmlNode>(),
                                         ancestor, new List <XmlNode>()).Run();
                return;
            }

            List <XmlNode> ourChildren;
            List <XmlNode> theirChildren;
            List <XmlNode> ancestorChildren;

            switch (strategy.NumberOfChildren)
            {
            default:
                throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.ZeroOrMore is not legal.");                         // Route tested.

            case NumberOfChildrenAllowed.Zero:
                ourChildren = GetElementChildren(ours).ToList();
                if (ourChildren.Any())
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.Zero is not legal, when there are child element nodes.");                             // Route tested.
                }
                theirChildren = GetElementChildren(theirs).ToList();
                if (theirChildren.Any())
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.Zero is not legal, when there are child element nodes.");                             // Route tested.
                }
                ancestorChildren = GetElementChildren(ancestor).ToList();
                if (ancestorChildren.Any())
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.Zero is not legal, when there are child element nodes.");                             // Route tested.
                }
                // Don't merge deeper than merging the attributes, since there aren't supposed to be any children.
                // Already done by caller MergeXmlAttributesService.MergeAttributes(merger, ref ours, theirs, ancestor);
                // Route tested.
                break;

            case NumberOfChildrenAllowed.ZeroOrOne:
                ourChildren = GetElementChildren(ours).ToList();
                if (ourChildren.Count > 1)
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.ZeroOrOne is not legal, when there are multiple child nodes.");                             // Route tested.
                }
                theirChildren = GetElementChildren(theirs).ToList();
                if (theirChildren.Count > 1)
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.ZeroOrOne is not legal, when there are multiple child nodes.");                             // Route tested.
                }
                ancestorChildren = GetElementChildren(ancestor).ToList();
                if (ancestorChildren.Count > 1)
                {
                    throw new InvalidOperationException("Using strategy with NumberOfChildren property of NumberOfChildrenAllowed.ZeroOrOne is not legal, when there are child element nodes.");                             // Route tested.
                }
                // Already done by caller MergeXmlAttributesService.MergeAttributes(merger, ref ours, theirs, ancestor);

                if (!ourChildren.Any() && !theirChildren.Any() && ancestor != null)
                {
                    return;                             // Route tested.
                }
                // The return value of Run may be the original 'ours', a replacement for it, or null.
                ours = Run(merger, ours, theirs, ancestor);                         // Route tested.
                break;
            }
        }
예제 #26
0
 public static ElementStrategy CreateForKeyedElement(string keyAttributeName, bool orderIsRelevant)
 {
     var strategy = new ElementStrategy(orderIsRelevant)
         {
             MergePartnerFinder = new FindByKeyAttribute(keyAttributeName)
         };
     return strategy;
 }
예제 #27
0
 /// <summary>
 /// Put in a special context generator for 'b', the element that is deleted.
 /// This should be used to generate the HTML.
 /// </summary>
 /// <param name="key"></param>
 /// <param name="strategy"></param>
 private void AddContextGenForB(string key, ElementStrategy strategy)
 {
     if (key != "b")
         return;
     strategy.ContextDescriptorGenerator = new EditDeleteContextGenerator();
 }
 internal static ElementStrategy AddSingletonElementType(MergeStrategies mergeStrategies, string name)
 {
     var strategy = new ElementStrategy(false)
                     {
                         MergePartnerFinder = new FindFirstElementWithSameName()
                     };
     mergeStrategies.SetStrategy(name, strategy);
     return strategy;
 }
예제 #29
0
 /* Called <pronunciation> in lift file.
 private static void AddPhoneticStrategy(MergeStrategies mergeStrategies)
 {
     var strategy = new ElementStrategy(false)
                     {
                         MergePartnerFinder = new FormMatchingFinder()
                     };
     strategy.AttributesToIgnoreForMerging.Add("dateModified");
     mergeStrategies.SetStrategy("phonetic", strategy);
 }*/
 private static void AddPronunciationStrategy(MergeStrategies mergeStrategies)
 {
     var strategy = new ElementStrategy(false)
                     {
                         MergePartnerFinder = new FormMatchingFinder()
                     };
     strategy.AttributesToIgnoreForMerging.Add("dateModified");
     mergeStrategies.SetStrategy("pronunciation", strategy);
 }
예제 #30
0
        /// <summary>
        /// Remove from ancestorKeepers any node that does not correspond to anything (both deleted)
        /// Remove from ancestorKeepers and theirKeepers any pair that correspond to each other but not to anything in ours. Report conflict (delete/edit) if pair not identical.
        /// Remove from ancestorKeepers and ourKeepers any pair that correspond to each other and are identical, but don't correspond to anything in theirs (they deleted)
        /// Report conflict (edit/delete) on any pair that correspond in ours and ancestor, but nothing in theirs, and that are NOT identical. (but keep them...we win)
        /// </summary>
        private void DoDeletions()
        {
            // loop over a copy of the list, since we may modify ancestorKeepers.
            List <XmlNode> loopSource    = new List <XmlNode>(_childrenOfAncestorKeepers);
            var            ourChildSet   = new HashSet <XmlNode>(_ours == null ? new XmlNode[0] : _ours.ChildNodes.Cast <XmlNode>());
            var            theirChildSet = new HashSet <XmlNode>(_theirs == null ? new XmlNode[0] : _theirs.ChildNodes.Cast <XmlNode>());

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

                var extantNode = ancestorChild ?? ourChild ?? theirChild;
                if (extantNode is XmlCharacterData)
                {
                    return;                     // Already done.
                }
                if (XmlUtilities.IsTextLevel(ourChild, theirChild, ancestorChild))
                {
                    new MergeTextNodesMethod(_merger, mergeStrategy, _skipInnerMergeFor,
                                             ref ourChild, _childrenOfOurKeepers,
                                             theirChild, _childrenOfTheirKeepers,
                                             ancestorChild, _childrenOfAncestorKeepers).DoDeletions();
                }
                else if (ourChild == null)
                {
                    // We deleted it.
                    if (theirChild == null)
                    {
                        // We both deleted it. Forget it ever existed.
                        // Route tested: MergeChildrenMethodTests.
                        _merger.EventListener.ChangeOccurred(new XmlBothDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild));
                        _childrenOfAncestorKeepers.Remove(ancestorChild);
                    }
                    else
                    {
                        if (!XmlUtilities.AreXmlElementsEqual(ancestorChild, theirChild))
                        {
                            // We deleted, they modified, report conflict.
                            if (theirChild.NodeType == XmlNodeType.Element)
                            {
                                // Route tested (XmlMergerTests).
                                _merger.ConflictOccurred(
                                    new RemovedVsEditedElementConflict(theirChild.Name, null,
                                                                       theirChild, ancestorChild,
                                                                       _merger.MergeSituation,
                                                                       _merger.MergeStrategies.GetElementStrategy(theirChild),
                                                                       _merger.MergeSituation.BetaUserId),
                                    theirChild);
                                _skipInnerMergeFor.Add(theirChild);
                            }
                            else
                            {
                                // Never used. But then, there isn't plain text in an xml file.
                                _merger.ConflictOccurred(
                                    new RemovedVsEditedTextConflict(null, theirChild,
                                                                    ancestorChild,
                                                                    _merger.MergeSituation,
                                                                    _merger.MergeSituation.BetaUserId));
                                _skipInnerMergeFor.Add(theirChild);
                            }
                            _childrenOfAncestorKeepers.Remove(ancestorChild);                            //review hatton added dec 2009, wanting whoever edited it to win (previously "we" always won)
                        }
                        else
                        {
                            //We deleted it, they didn't edit it. So just make it go away.
                            // Route tested in TextElementMergeTests, MergeChildrenMethod_DiffOnlyTests, XmlMergerTests
                            _merger.EventListener.ChangeOccurred(new XmlDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild, theirChild));
                            _childrenOfAncestorKeepers.Remove(ancestorChild);
                            _childrenOfTheirKeepers.Remove(theirChild);
                        }
                    }
                }
                else if (theirChild == null)
                {
                    // they deleted it (and we didn't)
                    if (XmlUtilities.AreXmlElementsEqual(ancestorChild, ourChild))
                    {
                        // We didn't touch it, allow their deletion to go forward, forget it existed.
                        // Route tested (XmlMergerTests).
                        _merger.EventListener.ChangeOccurred(new XmlDeletionChangeReport(_merger.MergeSituation.PathToFileInRepository, ancestorChild, ourChild));
                        _childrenOfAncestorKeepers.Remove(ancestorChild);
                        _childrenOfOurKeepers.Remove(ourChild);
                    }
                    else
                    {
                        // We changed it, ignore their deletion and report conflict.
                        if (ourChild.NodeType == XmlNodeType.Element)
                        {
                            // Route tested (XmlMergerTests).
                            _merger.ConflictOccurred(
                                new EditedVsRemovedElementConflict(ourChild.Name, ourChild, null, ancestorChild,
                                                                   _merger.MergeSituation, _merger.MergeStrategies.GetElementStrategy(ourChild), _merger.MergeSituation.AlphaUserId),
                                ourChild);
                            _skipInnerMergeFor.Add(ourChild);
                        }
                        else
                        {
                            // Never used. But then, there isn't plain text in an xml file.
                            _merger.ConflictOccurred(
                                new EditedVsRemovedTextConflict(ourChild, null, ancestorChild, _merger.MergeSituation, _merger.MergeSituation.AlphaUserId));
                            _skipInnerMergeFor.Add(ourChild);
                        }
                    }
                }
            }
        }
예제 #31
0
 private static void AddVariantStrategy(MergeStrategies mergeStrategies)
 {
     var strategy = new ElementStrategy(false)
                     {
                         MergePartnerFinder = new OptionalKeyAttrFinder("ref", new FormMatchingFinder())
                     };
     strategy.AttributesToIgnoreForMerging.Add("dateModified");
     mergeStrategies.SetStrategy("variant", strategy);
 }
        private static void MakeClassStrategy(MergeStrategies strategiesForMerger, FdoClassInfo classInfo, FieldWorkObjectContextGenerator defaultDescriptor)
        {
            Guard.AgainstNull(defaultDescriptor, "defaultDescriptor");

            // These values can be overridden or added to in the big switch, below.
            var classStrat = new ElementStrategy(false)
                {
                    ContextDescriptorGenerator = defaultDescriptor,
                    MergePartnerFinder = GuidKeyFinder,
                    IsAtomic = false
                };

            strategiesForMerger.SetStrategy(classInfo.ClassName, classStrat);

            // Try to keep these in alphbetical order, and where there are 'blocks', then try to keep the blocks in order.
            // That will make them easier to find.
            switch (classInfo.ClassName)
            {
                case "CmPossibilityList":
                    classStrat.ContextDescriptorGenerator = new PossibilityListContextGenerator();
                    break;
                case "FsClosedFeature":
                    classStrat.ContextDescriptorGenerator = new MultiLingualStringsContextGenerator("Phonological Features", "Name", "Abbreviation");
                    break;
                case "FsFeatStruc":
                    classStrat.IsAtomic = true;
                    break;
                case "LangProject":
                    classStrat.ContextDescriptorGenerator = new LanguageProjectContextGenerator();
                    break;
                case "LexEntry":
                    classStrat.ContextDescriptorGenerator = new LexEntryContextGenerator();
                    break;
                case "PhEnvironment":
                    classStrat.ContextDescriptorGenerator = new EnvironmentContextGenerator();
                    break;
                case "PhNCSegments":
                    classStrat.ContextDescriptorGenerator = new MultiLingualStringsContextGenerator("Natural Class", "Name", "Abbreviation");
                    break;
                case "ReversalIndexEntry":
                    classStrat.ContextDescriptorGenerator = new ReversalEntryContextGenerator();
                    break;
                case "RnGenericRec":
                    classStrat.ContextDescriptorGenerator = new RnGenericRecContextGenerator();
                    break;
                case "ScrBook":
                    classStrat.ContextDescriptorGenerator = new ScrBookContextGenerator();
                    break;
                case "ScrDraft":
                    // ScrDraft instances can only be added or removed, but not changed, according to John Wickberg (18 Jan 2012).
                    classStrat.IsImmutable = true;
                    break;
                case "ScrSection":
                    classStrat.ContextDescriptorGenerator = new ScrSectionContextGenerator();
                    break;
                case "ScrTxtPara": // Fall through.
                case "StTxtPara":
                    // This will never be used, since StTxtParas & ScrTxtParas are actually in an 'ownseq' element.
                    classStrat.Premerger = new StTxtParaPremerger();
                    // Didn't work, since StTxtParas & ScrTxtParas are actually in an 'ownseq' element.
                    // classStrat.IsAtomic = true;
                    break;
                case "Text":
                    classStrat.ContextDescriptorGenerator = new TextContextGenerator();
                    break;
                case "WfiWordform":
                    classStrat.ContextDescriptorGenerator = new WfiWordformContextGenerator();
                    break;

                // These should be all the subclasses of CmPossiblity. It's unfortuate to have to list them here;
                // OTOH, if we ever want special handling for any of them, we can easily add a special generator.
                // Note that these will not usually be found as strategies, since they are owned in owning sequences
                // and ownseq has its own item. However, they can be found by the default object context generator code,
                // which has a special case for ownseq.
                case "ChkTerm":
                case "CmAnthroItem":
                case "CmAnnotationDefn":
                case "CmCustomItem":
                case "CmLocation":
                case "CmPerson":
                case "CmPossibility":
                case "CmSemanticDomain":
                case "LexEntryType":
                case "LexRefType":
                case "MoMorphType":
                case "PartOfSpeech":
                case "PhPhonRuleFeat":
                    classStrat.ContextDescriptorGenerator = new PossibilityContextGenerator();
                    break;

                case "ConstChartRow":
                case "ConstChartWordGroup":
                case "DsConstChart":
                    classStrat.ContextDescriptorGenerator = new DiscourseChartContextGenerator();
                    break;
            }

            ((FieldWorkObjectContextGenerator)classStrat.ContextDescriptorGenerator).MergeStrategies = strategiesForMerger;
        }
 public void DefaultIsFalse()
 {
     var elementStrategy = new ElementStrategy(false);
     Assert.IsFalse(elementStrategy.IsAtomic);
 }
 public void UsingWith_NumberOfChildrenAllowed_Zero_DoesNotThrowWhenParentHasCommentChildNode()
 {
     var strategy = new ElementStrategy(false)
     {
         NumberOfChildren = NumberOfChildrenAllowed.Zero
     };
     var doc = new XmlDocument();
     var parent = doc.CreateNode(XmlNodeType.Element, "somenode", null);
     var comment = doc.CreateNode(XmlNodeType.Comment, "Some comment.", null);
     parent.AppendChild(comment);
     Assert.DoesNotThrow(() => MergeLimitedChildrenService.Run(new XmlMerger(new NullMergeSituation()), strategy, ref parent, parent, parent));
 }
 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;
 }
예제 #36
0
 public static ElementStrategy CreateForKeyedElementInList(string keyAttributeName)
 {
     var strategy = new ElementStrategy(true)
         {
             MergePartnerFinder = new FindByKeyAttributeInList(keyAttributeName)
         };
     return strategy;
 }
 private static void AddKeyedElementType(IDictionary<string, ElementStrategy> sharedElementStrategies, string elementName, IFindNodeToMerge findBykeyAttribute, bool orderOfTheseIsRelevant, bool isAtomic)
 {
     var strategy = new ElementStrategy(orderOfTheseIsRelevant)
                     {
                         MergePartnerFinder = findBykeyAttribute,
                         ContextDescriptorGenerator = ContextGen,
                         IsAtomic = isAtomic
                     };
     sharedElementStrategies.Add(elementName, strategy);
 }
 private static ElementStrategy CreateSingletonElementType(bool orderOfTheseIsRelevant)
 {
     var strategy = new ElementStrategy(orderOfTheseIsRelevant)
                     {
                         MergePartnerFinder = SameNameFinder,
                         ContextDescriptorGenerator = ContextGen
                     };
     return strategy;
 }
        /// <summary>
        /// Add all of the Lift range related ElementStrategy instacnes suitable for use in the lift file, and the lift-ranges file.
        ///
        /// This will likely over-populate mergeStrategies with strategies for the lift file, but no matter.
        /// </summary>
        /// <remarks>
        /// NB: There are more element strategies needed to support ranges, but they are expected to be defined elsewhere, as they are common to other non-range elements.
        /// Examples: "description" and "form" elements.
        /// </remarks>
        internal static void AddLiftBasicElementStrategies(MergeStrategies mergeStrategies)
        {
            // ******************************* <form> **************************************************
            // <form
            //		lang='lang' (required)
            AddKeyedElementType(mergeStrategies, "form", "lang", false);
            //		<text> (Required, sig of <text>)
            //		<annotation> [Optional, Multiple, sig=annotation]
            // </form>
            // ******************************* </form> **************************************************

            // ******************************* <text> **************************************************
            // Mixes text data and <span> elements
            // 'lang' attr from parent <form> element is the defacto same thing for the <text> element, but has no attrs itself.
            // <text>
            var textStrategy = AddSingletonElementType(mergeStrategies, "text");
            textStrategy.IsAtomic = true; // don't attempt merge within text elements if they have non-text-node children, e.g., <span>
            // but we can do text-level merging if there are no spans; this allows text editing conflicts to be reported
            // and multiple text nodes which amount to the same inner text to be ignored.
            textStrategy.AllowAtomicTextMerge = true;
            // </text>
            // ******************************* </text> **************************************************

            // ******************************* <span> **************************************************
            // <span
            //		lang='lang' (optional, so how can it really be used as a key to find a match?) NB: UML chart has it as 'string', not 'lang', but 'lang' is better for us
            var elementStrategy = ElementStrategy.CreateForKeyedElementInList("lang");
            //		href='URL' (optional, ignore?)
            elementStrategy.AttributesToIgnoreForMerging.Add("href");
            //		class='string'> (optional)
            //		<span> (optional, multiple)
            // </span>
            mergeStrategies.SetStrategy("span", elementStrategy);
            // ******************************* </span> **************************************************

            // ******************************* <multitext> **************************************************
            // Formally 'inherits' from <text>, so has all it has (parent 'lang' attr governs, and other <text> rules on <span>, etc.).
            // Gotchas:
            //	1. There are no occurrences of a span being used to store content except as part of a multitext.
            //	2. text [Optional] If there is only one form the form element itself is optional and a multitext
            //		may consist of a single text node containing the contents of the text.
            //		This means that if there is no form there is no span capability.
            // <multitext		No attrs
            //		<form> [Optional, Multiple, sig=form]
            // </multitext>
            // Note: If it is 'abstract', then no element strategy is needed.
            // ******************************* </multitext> **************************************************

            // ******************************* <URLRef> **************************************************
            // <URLRef> element never occurs in the wild, as it always gets a name change.
            // <URLRef
            //		href="URL" [Required, sig=URL]
            //		<label> [Optional, sig=multitext]
            AddSingletonElementType(mergeStrategies, "label");
            // </URLRef>
            // ******************************* </URLRef> **************************************************

            // ******************************* <annotation> **************************************************
            // <annotation
            //		name [Required, key]
            //		value [Required, key]
            elementStrategy = new ElementStrategy(false)
            {
                // Need both keys to find the match.
                MergePartnerFinder = new FindByMultipleKeyAttributes(new List<string> { "name", "value" })
            };
            mergeStrategies.SetStrategy("annotation", elementStrategy);
            //		who  [Optional, key]
            //		when  [Optional, key]
            //		<form> [Optional, Multiple, sig=form, inherited from <multitext>]
            // </annotation>
            // ******************************* </annotation> **************************************************

            // Shared with <header> in lift file, <range-element> and <range> in lift and lift-ranges files.
            elementStrategy = AddSingletonElementType(mergeStrategies, "description");
            elementStrategy.OrderIsRelevant = false;
        }
예제 #40
0
 private void DoTextMerge(ref XmlNode ours, XmlNode theirs, XmlNode ancestor, ElementStrategy elementStrat)
 {
     new MergeTextNodesMethod(this, elementStrat, new HashSet <XmlNode>(), ref ours, new List <XmlNode>(), theirs,
                              new List <XmlNode>(), ancestor, new List <XmlNode>()).Run();
 }