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; }
/// <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; }