private static ElementStrategy MakeClassStrategy(FieldWorkObjectContextGenerator descriptor, MergeStrategies strategies)
		{
			var classStrat = new ElementStrategy(false)
			{
				MergePartnerFinder = GuidKey,
				ContextDescriptorGenerator = descriptor,
				IsAtomic = false
			};
			descriptor.MergeStrategies = strategies;
			return classStrat;
		}
		public void UnknownMultiStringDefault()
		{
			string source =
				@"<RootClass>
					<HomographNumber
						val='0' />
					<Outer>
						<Mid>
							<Target>
								<AUni ws='en'>abcdefghijk</AUni>
								<AUni ws='fr'>other</AUni>
							</Target>
							<IsAbstract
								val='False' />
							<MorphType>
								<objsur
									guid='d7f713e4-e8cf-11d3-9764-00c04f186933'
									t='r' />
							</MorphType>
						</Mid>
					</Outer>
				</RootClass>";
			var root = GetNode(source);
			var input = root.ChildNodes[1].ChildNodes[0].ChildNodes[0]; // the Target element.
			var generator = new FieldWorkObjectContextGenerator();
			var html = generator.HtmlContext(input);
			Assert.That(html.StartsWith("<div>"));
			Assert.That(html, Contains.Substring("<div><span class=\"ws\">en</span>: abcdefghijk</div>"));
			Assert.That(html, Contains.Substring("<div><span class=\"ws\">fr</span>: other</div>"));

			// Get exactly the same starting from one of the AUni children.
			var input2 = input.ChildNodes[1];
			html = generator.HtmlContext(input2);
			Assert.That(html.StartsWith("<div>"));
			Assert.That(html, Contains.Substring("<div><span class=\"ws\">en</span>: abcdefghijk</div>"));
			Assert.That(html, Contains.Substring("<div><span class=\"ws\">fr</span>: other</div>"));
		}
		private static FieldWorkObjectContextGenerator MakeGenerator()
		{
			var result = new FieldWorkObjectContextGenerator();
			var strategies = new MergeStrategies();
			result.MergeStrategies = strategies;
			strategies.SetStrategy("LexEntry", MakeClassStrategy(new LexEntryContextGenerator(), strategies));
			strategies.SetStrategy("ReversalIndexEntry", MakeClassStrategy(new ReversalEntryContextGenerator(), strategies));
			strategies.SetStrategy("WfiWordform", MakeClassStrategy(new WfiWordformContextGenerator(), strategies));
			strategies.SetStrategy("CmPossibilityList", MakeClassStrategy(new PossibilityListContextGenerator(), strategies));
			strategies.SetStrategy("CmPossibility", MakeClassStrategy(new PossibilityContextGenerator(), strategies));
			strategies.SetStrategy("LexEntryType", MakeClassStrategy(new PossibilityContextGenerator(), strategies));
			strategies.SetStrategy("PhEnvironment", MakeClassStrategy(new EnvironmentContextGenerator(), strategies));
			strategies.SetStrategy("DsChart", MakeClassStrategy(new DiscourseChartContextGenerator(), strategies));
			strategies.SetStrategy("DsConstChart", MakeClassStrategy(new DiscourseChartContextGenerator(), strategies));
			strategies.SetStrategy("ConstChartRow", MakeClassStrategy(new DiscourseChartContextGenerator(), strategies));
			strategies.SetStrategy("ConstChartWordGroup", MakeClassStrategy(new DiscourseChartContextGenerator(), strategies));
			strategies.SetStrategy("PhNCSegments", MakeClassStrategy(new MultiLingualStringsContextGenerator("Natural Class", "Name", "Abbreviation"), strategies));
			strategies.SetStrategy("FsClosedFeature", MakeClassStrategy(new MultiLingualStringsContextGenerator("Phonological Features", "Name", "Abbreviation"), strategies));
			strategies.SetStrategy("Text", MakeClassStrategy(new TextContextGenerator(), strategies));
			strategies.SetStrategy("RnGenericRec", MakeClassStrategy(new RnGenericRecContextGenerator(), strategies));
			strategies.SetStrategy("ScrBook", MakeClassStrategy(new ScrBookContextGenerator(), strategies));
			strategies.SetStrategy("ScrSection", MakeClassStrategy(new ScrSectionContextGenerator(), strategies));
			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;
        }
		public void TestFirstNonBlankChildsData()
		{
			const string source = @"	<ArbitraryLabel
						guid='1ee09905-63dd-4c7a-a9bd-1d496743ccd6'>
						<Name>
							<AUni ws='fr'></AUni>
							<AUni ws='fa'>   </AUni>
							<AUni ws='hi'>	</AUni>
							<AUni ws='en'>The Name</AUni>
						</Name>
					</ArbitraryLabel>";
			var root = FieldWorksTestServices.GetNode(source);
			var input = root.ChildNodes[0];
			var generator = new FieldWorkObjectContextGenerator();

			Assert.That(generator.FirstNonBlankChildsData(input), Is.EqualTo("The Name"));
		}
		public void LastResortIsGenericHtmlGenerator()
		{
			string source =
			@"<RootClass>
					<Outer>
						<Mid>
							<Target>
								some rubbish
							</Target>
						</Mid>
					</Outer>
				</RootClass>";
			var root = GetNode(source);
			var input = root.ChildNodes[0].ChildNodes[0].ChildNodes[0]; // the Target element.
			var generator = new FieldWorkObjectContextGenerator();
			var html = generator.HtmlContext(input);
			Assert.That(html, Is.EqualTo(new FwGenericHtmlGenerator().MakeHtml(input)));
		}
		public void UnicodeStringJustShowsText()
		{
			string source =
				@"<RootClass>
					<HomographNumber
						val='0' />
					<Outer>
						<Mid>
							<Target>
								<Uni>abcdefghijk</Uni>
							</Target>

						</Mid>
					</Outer>
				</RootClass>";
			var root = GetNode(source);
			var input = root.ChildNodes[1].ChildNodes[0].ChildNodes[0]; // the Target element.
			var generator = new FieldWorkObjectContextGenerator();
			var html = generator.HtmlContext(input);
			Assert.That(html, Is.EqualTo("abcdefghijk"));

			// Get exactly the same starting from  the Uni child.
			var input2 = input.ChildNodes[0];
			html = generator.HtmlContext(input2);
			Assert.That(html, Is.EqualTo("abcdefghijk"));
		}