private static void CheckNewPropertyAfterUpgrade(FdoClassInfo classInfo, string newPropName, DataType dataType)
        {
            var newProperty = GetProperty(classInfo, newPropName);

            Assert.IsNotNull(newProperty, string.Format("{0} {1} should exist now.", classInfo.ClassName, newPropName));
            Assert.AreEqual(dataType, newProperty.DataType, string.Format("{0} {1} data type should be {2}.", classInfo.ClassName, newPropName, dataType));
        }
Example #2
0
        private static string ChangeGuids(MetadataCache mdc, FdoClassInfo classInfo, XElement element)
        {
            var newGuid = Guid.NewGuid().ToString().ToLowerInvariant();

            element.Attribute(SharedConstants.GuidStr).Value = newGuid;

            // Recurse down through everything that is owned and change those guids.
            foreach (var owningPropInfo in classInfo.AllOwningProperties)
            {
                var isCustomProp      = owningPropInfo.IsCustomProperty;
                var owningPropElement = isCustomProp
                                                                                        ? (element.Elements(SharedConstants.Custom).Where(customProp => customProp.Attribute(SharedConstants.Name).Value == owningPropInfo.PropertyName)).FirstOrDefault()
                                                                                        : element.Element(owningPropInfo.PropertyName);
                if (owningPropElement == null || !owningPropElement.HasElements)
                {
                    continue;
                }
                foreach (var ownedElement in owningPropElement.Elements())
                {
                    FdoClassInfo ownedClassInfo;
                    string       className;
                    GetClassInfoFromElement(mdc, element, out ownedClassInfo, out className);
                    ChangeGuids(mdc, ownedClassInfo, ownedElement);
                }
            }

            return(newGuid);
        }
Example #3
0
        private static void CheckNewPropertyAfterUpgrade(FdoClassInfo classInfo, string newPropName, DataType dataType)
        {
            var newProperty = (from propInfo in classInfo.AllProperties
                               where propInfo.PropertyName == newPropName
                               select propInfo).FirstOrDefault();

            Assert.IsNotNull(newProperty, string.Format("{0} {1} should exist now.", classInfo.ClassName, newPropName));
            Assert.AreEqual(dataType, newProperty.DataType, string.Format("{0} {1} data type should be {2}.", classInfo.ClassName, newPropName, dataType));
        }
        /// <summary>
        /// Gets the 'label' attribute of the custom property, if present, or its 'name', if not present.
        /// </summary>
        /// <param name="classname">Class name that is supposed to contain the given custom property.</param>
        /// <param name="customPropertyName">Name from Custom element which is an ancestor of styleRules (for a custom field)</param>
        /// <returns>The label of the custom field if it has one. Otherwise, the custom property name.</returns>
        public string GetDisplayName(string classname, string customPropertyName)
        {
            var          mdc       = MetadataCache.MdCache;
            FdoClassInfo classInfo = null;

            if (string.IsNullOrEmpty(classname))
            {
                // Find it the hard way.
                foreach (var fdoClassInfo in mdc.AllClasses
                         .Where(fdoClassInfo => fdoClassInfo.AllProperties.Any(propInf => propInf.DataType == DataType.TextPropBinary && propInf.PropertyName == customPropertyName)))
                {
                    classInfo = fdoClassInfo;
                    break;
                }
            }
            else
            {
                classInfo = mdc.GetClassInfo(classname);
            }
            if (classInfo == null)
            {
                return(customPropertyName);
            }

            var propInfo = classInfo.GetProperty(customPropertyName);

            if (propInfo == null || !propInfo.IsCustomProperty)
            {
                return(customPropertyName);
            }

            var allPropInfo = propInfo.AllPropertyValues;

            return(allPropInfo.ContainsKey(SharedConstants.Label)
                                           ? allPropInfo[SharedConstants.Label]
                                           : customPropertyName);
        }
Example #5
0
        private static FdoClassInfo CheckClassDoesExistAfterUpGrade(MetadataCache mdc, FdoClassInfo superclass, string newClassname)
        {
            var result = mdc.GetClassInfo(newClassname);

            Assert.IsNotNull(result);
            Assert.AreSame(superclass, result.Superclass);
            return(result);
        }
        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;
        }
        private static void AddPropertyStrategiesForClass(MergeStrategies strategiesForMerger, FdoClassInfo classInfo)
        {
            foreach (var propertyInfo in classInfo.AllProperties)
            {
                var isCustom = propertyInfo.IsCustomProperty;
                var propStrategy = isCustom
                                       ? CreateStrategyForKeyedElement(SharedConstants.Name, false)
                                       : CreateSingletonElementStrategy();
                switch (propertyInfo.DataType)
                {
                    // Block of object properties

                    case DataType.OwningAtomic:
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                        break;
                    //case DataType.OwningCollection: // Nothing special done
                    //	break;
                    case DataType.OwningSequence:
                        if ((classInfo.ClassName == "CmPossibilityList" && propertyInfo.PropertyName == "Possibilities")
                            || (propertyInfo.PropertyName == "SubPossibilities" && classInfo.IsOrInheritsFrom("CmPossibility")))
                        {
                            // Order may or may not be significant in possibility lists and sublists, depending on whether the list is sorted.
                            propStrategy.ChildOrderPolicy = new PossibilityListOrderPolicy();
                        }
                        else
                        {
                            // Normally order is significant in owning sequences; no need to ask each child.
                            propStrategy.ChildOrderPolicy = new SignificantOrderPolicy();
                        }
                        break;
                    case DataType.ReferenceAtomic:
                        if (classInfo.ClassName == "LexSense" && propertyInfo.PropertyName == "MorphoSyntaxAnalysis")
                        {
                            propStrategy.ContextDescriptorGenerator = new PosContextGenerator();
                        }
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                        break;
                    //case DataType.ReferenceCollection: // Nothing special done
                    //	break;
                    case DataType.ReferenceSequence:
                        // Trying to merge the Analyses of a segment is problematic. Best to go all-or-nothing, and ensure
                        // we get a conflict report if it fails.
                        if (classInfo.ClassName == "Segment" && propertyInfo.PropertyName == "Analyses")
                            propStrategy.IsAtomic = true;
                        break;

                    // Block of multi-somethings
                    // In model, but nothing special done at the property element level
                    //case DataType.MultiString:
                    //    break;
                    //case DataType.MultiUnicode:
                    //    break;

                    // Block of other property data types
                    case DataType.Binary:
                        propStrategy.IsAtomic = true;
                        break;
                    case DataType.Boolean:
                        // LT-13320 "Date of Event is lost after send/receive (data loss)"
                        // says these fields don't play nice as immutable.
                        //if (classInfo.ClassName == "CmPerson" || classInfo.ClassName == "RnGenericRec")
                        //	propStrategy.IsImmutable = true; // Surely DateOfBirth, DateOfDeath, and DateOfEvent are fixed. onced they happen. :-)
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                        break;
                    //case DataType.Float: // Not used in model
                    //	break;
                    case DataType.GenDate:
                        // LT-13320 "Date of Event is lost after send/receive (data loss)"
                        // says these fields don't play nice as immutable.
                        //if (classInfo.ClassName == "CmPerson" || classInfo.ClassName == "RnGenericRec")
                        //	propStrategy.IsImmutable = true; // Surely DateOfBirth, DateOfDeath, and DateOfEvent are fixed. onced they happen. :-)
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                        break;
                    case DataType.Guid:
                        if (classInfo.ClassName == "CmFilter" || classInfo.ClassName == "CmResource")
                            propStrategy.IsImmutable = true;
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                        break;
                    case DataType.Integer: // Fall through
                        if (propertyInfo.PropertyName == "HomographNumber")
                        {
                            // Don't fret about conflicts in merging the homograph numbers.
                            propStrategy.AttributesToIgnoreForMerging.Add("val");
                        }
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                        break;
                    //case DataType.Numeric: // Not used in model
                    //	break;
                    case DataType.String: // Contains one <Str> element
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                        break;
                    case DataType.TextPropBinary:
                        propStrategy.ContextDescriptorGenerator = new StyleContextGenerator();
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                        break;
                    case DataType.Time:
                        if (propertyInfo.PropertyName == "DateCreated")
                        {
                            propStrategy.IsImmutable = true;
                        }
                        else
                        {
                            // Suppress conflicts and change reports for other date time properties, which currently are all
                            // some variation on modify time, or most recent run time.
                            // For all of them, it is appropriate to just keep the most recent.
                            propStrategy.Premerger = new PreferMostRecentTimePreMerger();
                        }
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                        break;
                    case DataType.Unicode: // Contains one <Uni> element
                        propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                        break;
                }
                strategiesForMerger.SetStrategy(
                    String.Format("{0}{1}_{2}", isCustom ? "Custom_" : "", classInfo.ClassName, propertyInfo.PropertyName), propStrategy);
            }
        }
Example #8
0
        private static bool EnsureBasicValueTypePropertyElementsExist(MetadataCache mdc, FdoClassInfo classInfo, XElement element, IEnumerable <string> basicPropertyNames, out string result)
        {
            result = null;

            if (mdc.ModelVersion < 7000066)
            {
                return(true);                // The value type data types are only required at DM 7000066, and higher.
            }
            foreach (var basicPropertyName in basicPropertyNames)
            {
                var currentPropName  = basicPropertyName;
                var isCustomProperty = classInfo.GetProperty(basicPropertyName).IsCustomProperty;
                var propertyElement  = isCustomProperty
                                        ? element.Elements("Custom").FirstOrDefault(propElement => propElement.Attribute(SharedConstants.Name).Value == currentPropName)
                                        : element.Element(currentPropName);
                if (propertyElement != null)
                {
                    continue;
                }

                result = string.Format("Required basic property element '{0}' of class '{1}' is missing.", currentPropName, classInfo.ClassName);
                return(false);
            }
            return(true);
        }
        private static bool EnsureBasicValueTypePropertyElementsExist(MetadataCache mdc, FdoClassInfo classInfo, XElement element, IEnumerable<string> basicPropertyNames, out string result)
        {
            result = null;

            if (mdc.ModelVersion < 7000066)
                return true; // The value type data types are only required at DM 7000066, and higher.

            foreach (var basicPropertyName in basicPropertyNames)
            {
                var currentPropName = basicPropertyName;
                var isCustomProperty = classInfo.GetProperty(basicPropertyName).IsCustomProperty;
                var propertyElement = isCustomProperty
                    ? element.Elements("Custom").FirstOrDefault(propElement => propElement.Attribute(SharedConstants.Name).Value == currentPropName)
                    : element.Element(currentPropName);
                if (propertyElement != null)
                    continue;

                result = string.Format("Required basic property element '{0}' of class '{1}' is missing.", currentPropName, classInfo.ClassName);
                return false;
            }
            return true;
        }
 private static FdoPropertyInfo GetProperty(FdoClassInfo classInfo, string propertyName)
 {
     return((from propInfo in classInfo.AllProperties
             where propInfo.PropertyName == propertyName
             select propInfo).FirstOrDefault());                    // May be null.
 }
Example #11
0
        private static bool GetClassInfoFromElement(MetadataCache mdc, XElement element, out FdoClassInfo classInfo,
                                                    out string className)
        {
            var isOwnSeqNode = element.Name.LocalName == SharedConstants.Ownseq;

            className = isOwnSeqNode ? element.Attribute(SharedConstants.Class).Value : element.Name.LocalName;
            classInfo = mdc.GetClassInfo(className);
            return(isOwnSeqNode);
        }
		private static string ChangeGuids(MetadataCache mdc, FdoClassInfo classInfo, XElement element)
		{
			var newGuid = Guid.NewGuid().ToString().ToLowerInvariant();

			element.Attribute(SharedConstants.GuidStr).Value = newGuid;

			// Recurse down through everything that is owned and change those guids.
			foreach (var owningPropInfo in classInfo.AllOwningProperties)
			{
				var isCustomProp = owningPropInfo.IsCustomProperty;
				var owningPropElement = isCustomProp
											? (element.Elements(SharedConstants.Custom).Where(customProp => customProp.Attribute(SharedConstants.Name).Value == owningPropInfo.PropertyName)).FirstOrDefault()
											: element.Element(owningPropInfo.PropertyName);
				if (owningPropElement == null || !owningPropElement.HasElements)
					continue;
				foreach (var ownedElement in owningPropElement.Elements())
				{
					FdoClassInfo ownedClassInfo;
					string className;
					GetClassInfoFromElement(mdc, element, out ownedClassInfo, out className);
					ChangeGuids(mdc, ownedClassInfo, ownedElement);
				}
			}

			return newGuid;
		}
		private static bool GetClassInfoFromElement(MetadataCache mdc, XElement element, out FdoClassInfo classInfo,
													out string className)
		{
			var isOwnSeqNode = element.Name.LocalName == SharedConstants.Ownseq;
			className = isOwnSeqNode ? element.Attribute(SharedConstants.Class).Value : element.Name.LocalName;
			classInfo = mdc.GetClassInfo(className);
			return isOwnSeqNode;
		}
Example #14
0
        private static void AddPropertyStrategiesForClass(MergeStrategies strategiesForMerger, FdoClassInfo classInfo)
        {
            foreach (var propertyInfo in classInfo.AllProperties)
            {
                var isCustom     = propertyInfo.IsCustomProperty;
                var propStrategy = isCustom
                                                                           ? CreateStrategyForKeyedElement(SharedConstants.Name, false)
                                                                           : CreateSingletonElementStrategy();
                switch (propertyInfo.DataType)
                {
                // Block of object properties

                case DataType.OwningAtomic:
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                    break;

                //case DataType.OwningCollection: // Nothing special done
                //	break;
                case DataType.OwningSequence:
                    if ((classInfo.ClassName == "CmPossibilityList" && propertyInfo.PropertyName == "Possibilities") ||
                        (propertyInfo.PropertyName == "SubPossibilities" && classInfo.IsOrInheritsFrom("CmPossibility")))
                    {
                        // Order may or may not be significant in possibility lists and sublists, depending on whether the list is sorted.
                        propStrategy.ChildOrderPolicy = new PossibilityListOrderPolicy();
                    }
                    else
                    {
                        // Normally order is significant in owning sequences; no need to ask each child.
                        propStrategy.ChildOrderPolicy = new SignificantOrderPolicy();
                    }
                    break;

                case DataType.ReferenceAtomic:
                    if (classInfo.ClassName == "LexSense" && propertyInfo.PropertyName == "MorphoSyntaxAnalysis")
                    {
                        propStrategy.ContextDescriptorGenerator = new PosContextGenerator();
                    }
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                    break;

                //case DataType.ReferenceCollection: // Nothing special done
                //	break;
                case DataType.ReferenceSequence:
                    // Trying to merge the Analyses of a segment is problematic. Best to go all-or-nothing, and ensure
                    // we get a conflict report if it fails.
                    if (classInfo.ClassName == "Segment" && propertyInfo.PropertyName == "Analyses")
                    {
                        propStrategy.IsAtomic = true;
                    }
                    break;

                // Block of multi-somethings
                // In model, but nothing special done at the property element level
                //case DataType.MultiString:
                //    break;
                //case DataType.MultiUnicode:
                //    break;

                // Block of other property data types
                case DataType.Binary:
                    propStrategy.IsAtomic = true;
                    break;

                case DataType.Boolean:
                    // LT-13320 "Date of Event is lost after send/receive (data loss)"
                    // says these fields don't play nice as immutable.
                    //if (classInfo.ClassName == "CmPerson" || classInfo.ClassName == "RnGenericRec")
                    //	propStrategy.IsImmutable = true; // Surely DateOfBirth, DateOfDeath, and DateOfEvent are fixed. onced they happen. :-)
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                    break;

                //case DataType.Float: // Not used in model
                //	break;
                case DataType.GenDate:
                    // LT-13320 "Date of Event is lost after send/receive (data loss)"
                    // says these fields don't play nice as immutable.
                    //if (classInfo.ClassName == "CmPerson" || classInfo.ClassName == "RnGenericRec")
                    //	propStrategy.IsImmutable = true; // Surely DateOfBirth, DateOfDeath, and DateOfEvent are fixed. onced they happen. :-)
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                    break;

                case DataType.Guid:
                    if (classInfo.ClassName == "CmFilter" || classInfo.ClassName == "CmResource")
                    {
                        propStrategy.IsImmutable = true;
                    }
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                    break;

                case DataType.Integer:                         // Fall through
                    if (propertyInfo.PropertyName == "HomographNumber")
                    {
                        // Don't fret about conflicts in merging the homograph numbers.
                        propStrategy.AttributesToIgnoreForMerging.Add("val");
                    }
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                    break;

                //case DataType.Numeric: // Not used in model
                //	break;
                case DataType.String:                         // Contains one <Str> element
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                    break;

                case DataType.TextPropBinary:
                    propStrategy.ContextDescriptorGenerator = new StyleContextGenerator();
                    propStrategy.NumberOfChildren           = NumberOfChildrenAllowed.ZeroOrOne;
                    break;

                case DataType.Time:
                    if (propertyInfo.PropertyName == "DateCreated")
                    {
                        propStrategy.IsImmutable = true;
                    }
                    else
                    {
                        // Suppress conflicts and change reports for other date time properties, which currently are all
                        // some variation on modify time, or most recent run time.
                        // For all of them, it is appropriate to just keep the most recent.
                        propStrategy.Premerger = new PreferMostRecentTimePreMerger();
                    }
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.Zero;
                    break;

                case DataType.Unicode:                         // Contains one <Uni> element
                    propStrategy.NumberOfChildren = NumberOfChildrenAllowed.ZeroOrOne;
                    break;
                }
                strategiesForMerger.SetStrategy(
                    String.Format("{0}{1}_{2}", isCustom ? "Custom_" : "", classInfo.ClassName, propertyInfo.PropertyName), propStrategy);
            }
        }
Example #15
0
        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;
        }