Wrapper for ICU methods
Example #1
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Test the character name at the memory address specified.
        /// Will assert an error if the PUA codepoint name is not correct.
        /// </summary>
        /// <param name="puaIndex">Unicode codepoint</param>
        /// <param name="puaName">Expected correct PUA codepoint name</param>
        /// <param name="puaGenCat">The expected PUA General Category</param>
        /// ------------------------------------------------------------------------------------
        public static void Check_PUA(int puaIndex, string puaName, LgGeneralCharCategory puaGenCat)
        {
            string name = string.Empty;
            LgGeneralCharCategory genCategory = LgGeneralCharCategory.kccCn;

            //Getting the character name at the memory address specified
            ILgCharacterPropertyEngine charPropEngine = LgIcuCharPropEngineClass.Create();

            try
            {
                FwIcu.UErrorCode            error;
                const FwIcu.UCharNameChoice choice = FwIcu.UCharNameChoice.U_UNICODE_CHAR_NAME;
                FwIcu.u_CharName(puaIndex, choice, out name, out error);
                genCategory = charPropEngine.get_GeneralCategory(puaIndex);
            }
            finally
            {
                // Must release pointer to free memory-mapping before we try to restore files.
                Marshal.ReleaseComObject(charPropEngine);
                charPropEngine = null;
                FwIcu.Cleanup();                                // clean up the ICU files / data
            }

            //Check to make sure expected result is the same as actual result, if not, output error
            Assert.AreEqual(puaName, name, "PUA Character " +
                            puaIndex.ToString("x", new System.Globalization.NumberFormatInfo()) +
                            " is incorrect");

            //Check to make sure expected result is the same as actual result, if not, output error
            Assert.AreEqual(puaGenCat, genCategory, "PUA Character " +
                            puaIndex.ToString("x", new System.Globalization.NumberFormatInfo()) +
                            " has an incorrect digit value");
        }
		private static XElement ExportLanguageProject(ILangProject languageProject, Icu.UNormalizationMode mode)
		{
			return new XElement("LangProject",
				new XElement("Name", languageProject.ShortName),
				ExportBestAnalysis(languageProject.Description, "Description", mode),
				ExportBestAnalysis(languageProject.MainCountry, "MainCountry", mode),
				ExportWritingSystems(languageProject.CurrentVernacularWritingSystems, "VernWss"),
				ExportWritingSystems(languageProject.CurrentAnalysisWritingSystems, "AnalysisWss"));
		}
Example #3
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Test the character name at the memory address specified.
        /// Will assert an error if the PUA codepoint name and digit value are not correct.
        /// </summary>
        /// <param name="puaIndex">Unicode codepoint</param>
        /// <param name="digit">Expected correct PUA codepoint name</param>
        /// ------------------------------------------------------------------------------------
        public static void Check_PUA_Digit(int puaIndex, int digit)
        {
            string name     = "";
            int    icuDigit = -1;

            //Getting the character name at the memory address specified
            FwIcu.UErrorCode      error;
            FwIcu.UCharNameChoice choice = FwIcu.UCharNameChoice.U_UNICODE_CHAR_NAME;
            FwIcu.u_CharName(puaIndex, choice, out name, out error);
            // Radix means "base", so this will return the base 10 value of this digit.
            // (Note, the radix is just used to return an error if the digit isn't valid in the given radix)
            icuDigit = FwIcu.u_Digit(puaIndex, 10);

            //Check to make sure expected result is the same as actual result, if not, output error
            Assert.AreEqual(digit, icuDigit, "PUA Character " +
                            puaIndex.ToString("x", new System.Globalization.NumberFormatInfo()) +
                            " has an incorrect digit value");
        }
		private static XElement ExportPhonRuleFeat(IPhPhonRuleFeat phonRuleFeat, Icu.UNormalizationMode mode)
		{
			return new XElement("PhonRuleFeat",
								new XAttribute("Id", phonRuleFeat.Hvo),
								ExportBestAnalysis(phonRuleFeat.Name, "Name", mode),
								new XElement("Item",
								phonRuleFeat.ItemRA != null ? new XAttribute("itemRef", phonRuleFeat.ItemRA.Hvo) : new XAttribute("missing", 1)));
		}
		private static void ExportPartOfSpeech(IPartOfSpeech pos, ICollection<XElement> cats, Icu.UNormalizationMode mode)
		{
			// Add 'pos'.
			cats.Add(new XElement("PartOfSpeech",
								  new XAttribute("Id", pos.Hvo),
								CreateAttribute("DefaultInflectionClass", pos.DefaultInflectionClassRA),
								  ExportBestAnalysis(pos.Name, "Name", mode),
								  ExportBestAnalysis(pos.Description, "Description", mode),
								  ExportBestAnalysis(pos.Abbreviation, "Abbreviation", mode),
								  new XElement("NumberOfLexEntries", pos.NumberOfLexEntries),
								  new XElement("AffixSlots",
											   from affixSlot in pos.AffixSlotsOC
											   where IsValidSlot(affixSlot)
											   select new XElement("MoInflAffixSlot",
																	new XAttribute("Id", affixSlot.Hvo),
																	new XAttribute("Optional", affixSlot.Optional),
																	ExportBestAnalysis(affixSlot.Name, "Name", mode),
																	ExportBestAnalysis(affixSlot.Description, "Description", mode))),
				// Affix templates.
								  new XElement("AffixTemplates", from template in pos.AffixTemplatesOS where IsValidTemplate(template)
																  select ExportAffixtemplate(template, mode)),
				// Inflection classes.
								  new XElement("InflectionClasses", from inflectionClass in pos.InflectionClassesOC
																	 select ExportInflectionClass(inflectionClass, mode)),
				// Inflectable Features
								  new XElement("InflectableFeats", from inflectableFeature in pos.InflectableFeatsRC
																   select new XElement("InflectableFeature",
																	   CreateDstAttribute(inflectableFeature.Hvo))),
				// Stem names
								  new XElement("StemNames", from stemName in pos.StemNamesOC
															 select ExportStemName(stemName, mode)),
				// BearableFeatures
								  new XElement("BearableFeatures",
											   from bearableFeaature in pos.BearableFeaturesRC
												select new XElement("BearableFeature",
																	CreateDstAttribute(bearableFeaature.Hvo))),
								  from subpos in pos.SubPossibilitiesOS
								   select ExportItemAsReference(subpos, "SubPossibilities")));

			// Add owned parts of speech.
			foreach (IPartOfSpeech innerPos in pos.SubPossibilitiesOS)
				ExportPartOfSpeech(innerPos, cats, mode);
		}
		private static XElement ExportPhonRuleFeats(IPhPhonData phonData, Icu.UNormalizationMode mode)
		{
			return new XElement("PhonRuleFeats",
				from phonRuleFeat in phonData.PhonRuleFeatsOA.ReallyReallyAllPossibilities
				select ExportPhonRuleFeat(phonRuleFeat as IPhPhonRuleFeat, mode));
		}
		private static XElement ExportStemName(IMoStemName stemName, Icu.UNormalizationMode mode)
		{
			return new XElement("MoStemName",
								new XAttribute("Id", stemName.Hvo),
								ExportBestAnalysis(stemName.Name, "Name", mode),
								ExportBestAnalysis(stemName.Description, "Description", mode),
								ExportBestAnalysis(stemName.Abbreviation, "Abbreviation", mode),
								new XElement("Regions", from region in stemName.RegionsOC
														 select ExportFeatureStructure(region)));
		}
		private static XElement ExportFeatureDefn(IFsFeatDefn featureDefn, Icu.UNormalizationMode mode)
		{
			switch (featureDefn.ClassName)
			{
				default:
					// FsOpenFeature doesn't appear to be exported as of 14 November 2009.
					throw new ArgumentException("Unrecognized IFsFeatDefn");
				case "FsClosedFeature":
					var closedFD = (IFsClosedFeature)featureDefn;
					return new XElement("FsClosedFeature",
						new XAttribute("Id", featureDefn.Hvo),
						ExportBestAnalysis(featureDefn.Name, "Name", mode),
						ExportBestAnalysis(featureDefn.Description, "Description", mode),
						ExportBestAnalysis(closedFD.Abbreviation, "Abbreviation", mode),
						new XElement("Values",
							from value in closedFD.ValuesOC
								 select new XElement("FsSymFeatVal",
									 new XAttribute("Id", value.Hvo),
									 ExportBestAnalysis(value.Name, "Name", mode),
									 ExportBestAnalysis(value.Description, "Description", mode),
									 ExportBestAnalysis(value.Abbreviation, "Abbreviation", mode))));
				case "FsComplexFeature":
					var complexFD = (IFsComplexFeature) featureDefn;
					return new XElement("FsComplexFeature",
						new XAttribute("Id", featureDefn.Hvo),
						ExportBestAnalysis(featureDefn.Name, "Name", mode),
						ExportBestAnalysis(featureDefn.Description, "Description", mode),
						ExportBestAnalysis(complexFD.Abbreviation, "Abbreviation", mode),
						ExportItemAsReference(complexFD.TypeRA, "Type"));
			}
		}
		private static XElement ExportBoundaryMarker(IPhBdryMarker bdryMarker, Icu.UNormalizationMode mode)
		{
			return new XElement("PhBdryMarker",
								new XAttribute("Id", bdryMarker.Hvo),
								new XAttribute("Guid", bdryMarker.Guid.ToString()),
								ExportBestAnalysis(bdryMarker.Name, "Name", mode),
								ExportCodes(bdryMarker.CodesOS, mode));
		}
		private static XElement ExportCodes(IEnumerable<IPhCode> codes, Icu.UNormalizationMode mode)
		{
			return new XElement("Codes", from phone in codes
										  select new XElement("PhCode",
															  new XAttribute("Id", phone.Hvo),
															  ExportBestVernacularOrAnalysis(phone.Representation,
																							 "Representation", mode)));
		}
		private static XElement ExportProdRestrict(IMoMorphData morphData, Icu.UNormalizationMode mode)
		{
			return new XElement("ProdRestrict",
				from restriction in morphData.ProdRestrictOA.ReallyReallyAllPossibilities
				select new XElement("CmPossibility",
					new XAttribute("Id", restriction.Hvo),
					ExportBestAnalysis(restriction.Name, "Name", mode),
					ExportBestAnalysis(restriction.Description, "Description", mode),
					ExportBestAnalysis(restriction.Abbreviation, "Abbreviation", mode)));
		}
		private static XElement ExportMorphTypes(IRepository<IMoMorphType> morphTypeRepository, Icu.UNormalizationMode mode)
		{
			return new XElement("MoMorphTypes",
				from morphType in morphTypeRepository.AllInstances()
				select new XElement("MoMorphType",
					new XAttribute("Id", morphType.Hvo),
					new XAttribute("Guid", morphType.Guid.ToString()),
					ExportBestAnalysis(morphType.Name, "Name", mode),
					ExportBestAnalysis(morphType.Abbreviation, "Abbreviation", mode),
					ExportBestAnalysis(morphType.Description, "Description", mode),
					new XElement("NumberOfLexEntries", morphType.NumberOfLexEntries)));
		}
		private static XElement ExportAdhocCoProhibition(IMoAdhocProhib adhocProhib, Icu.UNormalizationMode mode)
		{
			switch (adhocProhib.ClassID)
			{
				case MoAdhocProhibGrTags.kClassId:
					return ExportAdhocCoProhibitionGroup((IMoAdhocProhibGr) adhocProhib, mode);
				case MoMorphAdhocProhibTags.kClassId:
					return ExportMorphAdhocCoProhibition((IMoMorphAdhocProhib) adhocProhib);
				case MoAlloAdhocProhibTags.kClassId:
					return ExportAlloAdhocCoProhibition((IMoAlloAdhocProhib) adhocProhib);
			}
			return null;
		}
		private static XElement ExportAdhocCoProhibitionGroup(IMoAdhocProhibGr adhocProhibGr, Icu.UNormalizationMode mode)
		{
			return new XElement("MoAdhocProhibGr",
				new XAttribute("Id", adhocProhibGr.Hvo),
				ExportBestAnalysis(adhocProhibGr.Name, "Name", mode),
				ExportBestAnalysis(adhocProhibGr.Description, "Description", mode),
				from adhocCoProhib in adhocProhibGr.MembersOC
				where !adhocCoProhib.Disabled
				select ExportAdhocCoProhibition(adhocCoProhib, mode));
		}
		private static XElement ExportAdhocCoProhibitions(IMoMorphData morphData, Icu.UNormalizationMode mode)
		{
			return new XElement("AdhocCoProhibitions",
				from adhocCoProhib in morphData.AdhocCoProhibitionsOC
				where !adhocCoProhib.Disabled
				select ExportAdhocCoProhibition(adhocCoProhib, mode));
		}
		private static XElement ExportCompoundRules(IRepository<IMoEndoCompound> endoCmpRepository, IRepository<IMoExoCompound> exoCmpRepository,
			Icu.UNormalizationMode mode)
		{
			return new XElement("CompoundRules",
				from endoCompound in endoCmpRepository.AllInstances()
				where !endoCompound.Disabled
				select new XElement("MoEndoCompound",
					new XAttribute("Id", endoCompound.Hvo),
					new XAttribute("HeadLast", endoCompound.HeadLast ? 1 : 0),
					ExportBestAnalysis(endoCompound.Name, "Name", mode),
					ExportBestAnalysis(endoCompound.Description, "Description", mode),
					ExportItemAsReference(endoCompound.LeftMsaOA, "LeftMsa"),
					ExportItemAsReference(endoCompound.RightMsaOA, "RightMsa"),
					from prod in endoCompound.ToProdRestrictRC
					select ExportItemAsReference(prod, "ToProdRestrict"),
					ExportItemAsReference(endoCompound.OverridingMsaOA, "OverridingMsa")),
				from exoCompound in exoCmpRepository.AllInstances()
				where !exoCompound.Disabled
				select new XElement("MoExoCompound",
					new XAttribute("Id", exoCompound.Hvo),
					ExportBestAnalysis(exoCompound.Name, "Name", mode),
					ExportBestAnalysis(exoCompound.Description, "Description", mode),
					ExportItemAsReference(exoCompound.LeftMsaOA, "LeftMsa"),
					ExportItemAsReference(exoCompound.RightMsaOA, "RightMsa"),
					from prod in exoCompound.ToProdRestrictRC
					select ExportItemAsReference(prod, "ToProdRestrict"),
					ExportItemAsReference(exoCompound.ToMsaOA, "ToMsa")));
		}
		private static XElement ExportParserParameters(IMoMorphData morphologicalData, Icu.UNormalizationMode mode)
		{
			return new XElement("ParserParameters",
								XElement.Parse(Normalize(morphologicalData.ParserParameters, mode)));
		}
		private static XElement ExportPhonRule(IPhSegmentRule phonRule, Icu.UNormalizationMode mode)
		{
			if (phonRule.Disabled)
				return null;
			XElement retVal = null;
			switch (phonRule.ClassName)
			{
				case "PhMetathesisRule":
					var asMetathesisRule = (IPhMetathesisRule)phonRule;
					retVal = new XElement("PhMetathesisRule",
						new XAttribute("Id", phonRule.Hvo),
						new XAttribute("Direction", phonRule.Direction),
						ExportBestAnalysis(phonRule.Name, "Name", mode),
						ExportBestAnalysis(phonRule.Description, "Description", mode),
						new XElement("StrucDesc",
							ExportContextList(phonRule.StrucDescOS)),
						new XElement("StrucChange", asMetathesisRule.StrucChange.Text));
					break;
				case "PhRegularRule":
					var asRegularRule = (IPhRegularRule) phonRule;
					var constraints = new List<IPhFeatureConstraint>(asRegularRule.FeatureConstraints);
					retVal = new XElement("PhRegularRule",
						new XAttribute("Id", phonRule.Hvo),
						new XAttribute("Direction", phonRule.Direction),
						ExportBestAnalysis(phonRule.Name, "Name", mode),
						ExportBestAnalysis(phonRule.Description, "Description", mode),
						new XElement("StrucDesc",
							ExportContextList(phonRule.StrucDescOS)),
						from constraint in constraints
						select ExportItemAsReference(constraint, constraints.IndexOf(constraint), "FeatureConstraints"),
							new XElement("RightHandSides", from rhs in asRegularRule.RightHandSidesOS
														select new XElement("PhSegRuleRHS",
							new XAttribute("Id", rhs.Hvo),
							new XElement("StrucChange", from structChange in rhs.StrucChangeOS
															select ExportContext(structChange)),
							new XElement("InputPOSes", from pos in rhs.InputPOSesRC
															select ExportItemAsReference(pos, "RequiredPOS")),
							new XElement("ReqRuleFeats", from rrf in rhs.ReqRuleFeatsRC
															select ExportItemAsReference(rrf, "RuleFeat")),
							new XElement("ExclRuleFeats", from erf in rhs.ExclRuleFeatsRC
															select ExportItemAsReference(erf, "RuleFeat")),
							new XElement("LeftContext", ExportContext(rhs.LeftContextOA)),
							new XElement("RightContext", ExportContext(rhs.RightContextOA)))));
					break;
				case "PhSegmentRule":
					retVal = new XElement("PhSegmentRule",
						new XAttribute("Id", phonRule.Hvo),
						new XAttribute("Direction", phonRule.Direction),
						CreateAttribute("ord", phonRule.IndexInOwner),
						ExportBestAnalysis(phonRule.Name, "Name", mode),
						ExportBestAnalysis(phonRule.Description, "Description", mode),
						new XElement("StrucDesc",
							ExportContextList(phonRule.StrucDescOS)));
					break;
			}

			return retVal;
		}
		private static XElement ExportLexEntryInflTypes(IRepository<ILexEntryInflType> irregularlyInflectedFormTypeRepository, Icu.UNormalizationMode mode)
		{
			return new XElement("LexEntryInflTypes",
								from irregularlyInflectedForm in irregularlyInflectedFormTypeRepository.AllInstances()
								select new XElement("LexEntryInflType",
													new XAttribute("Id", irregularlyInflectedForm.Hvo),
													new XAttribute("Guid", irregularlyInflectedForm.Guid.ToString()),
													ExportBestAnalysis(irregularlyInflectedForm.Name, "Name", mode),
													ExportBestAnalysis(irregularlyInflectedForm.Abbreviation, "Abbreviation",
																	   mode),
													ExportBestAnalysis(irregularlyInflectedForm.Description, "Description", mode),
													ExportBestAnalysis(irregularlyInflectedForm.GlossPrepend, "GlossPrepend", mode),
													ExportBestAnalysis(irregularlyInflectedForm.GlossAppend, "GlossAppend", mode),
													from slot in irregularlyInflectedForm.SlotsRC
													select ExportItemAsReference(slot, "Slots"),
													new XElement("InflectionFeatures",
																 ExportFeatureStructure(irregularlyInflectedForm.InflFeatsOA))));
		}
		private static XElement ExportPhonemeSet(IPhPhonemeSet phonemeSet, Icu.UNormalizationMode mode)
		{
			return new XElement("PhPhonemeSet",
								new XAttribute("Id", phonemeSet.Hvo),
								ExportBestAnalysis(phonemeSet.Name, "Name", mode),
								ExportBestAnalysis(phonemeSet.Description, "Description", mode),
								new XElement("Phonemes", from phoneme in phonemeSet.PhonemesOC
														  select ExportPhoneme(phoneme, mode)),
								new XElement("BoundaryMarkers", from marker in phonemeSet.BoundaryMarkersOC
																 select ExportBoundaryMarker(marker, mode)));
		}
		/// <summary>
		/// Export the full lexicon when exporting both grammar and lexicon.
		/// </summary>
		private static XElement ExportLexiconFull(IServiceLocator servLoc, Icu.UNormalizationMode mode)
		{
			return new XElement("Lexicon",
					ExportEntries(servLoc.GetInstance<ILexEntryRepository>()),
					ExportMsas(servLoc),
					ExportSenses(servLoc.GetInstance<ILexSenseRepository>(), mode),
					ExportAllomorphs(servLoc, mode));
		}
		private static XElement ExportPhoneme(IPhPhoneme phoneme, Icu.UNormalizationMode mode)
		{
			return new XElement("PhPhoneme",
								new XAttribute("Id", phoneme.Hvo),
								ExportBestVernacular(phoneme.Name, "Name", mode),
								ExportBestAnalysis(phoneme.Description, "Description", mode),
								ExportCodes(phoneme.CodesOS, mode),
								new XElement("BasicIPASymbol", phoneme.BasicIPASymbol.Text),
								new XElement("PhonologicalFeatures", ExportFeatureStructure(phoneme.FeaturesOA)));
		}
		private static XElement ExportInflectionClass(IMoInflClass inflectionClass, Icu.UNormalizationMode mode)
		{
			return new XElement("MoInflClass",
								new XAttribute("Id", inflectionClass.Hvo),
								ExportBestAnalysis(inflectionClass.Name, "Name", mode),
								ExportBestAnalysis(inflectionClass.Abbreviation, "Abbreviation", mode),
								ExportBestAnalysis(inflectionClass.Description, "Description", mode),
								new XElement("Subclasses", from inflClass in inflectionClass.SubclassesOC
															select ExportInflectionClass(inflClass, mode)));
		}
		private static XElement ExportNaturalClass(IPhNaturalClass naturalClass, Icu.UNormalizationMode mode)
		{
			return new XElement(naturalClass.ClassName,
								new XAttribute("Id", naturalClass.Hvo),
								ExportBestAnalysis(naturalClass.Name, "Name", mode),
								ExportBestAnalysis(naturalClass.Description, "Description", mode),
								ExportBestAnalysis(naturalClass.Abbreviation, "Abbreviation", mode),
								(naturalClass is IPhNCFeatures)
									? ExportNaturalClassContents(naturalClass as IPhNCFeatures)
									: ExportNaturalClassContents(naturalClass as IPhNCSegments));
		}
		private static XElement ExportBestVernacularOrAnalysis(IMultiAccessorBase multiString, string elementName, Icu.UNormalizationMode mode)
		{
			if (multiString == null) throw new ArgumentNullException("multiString");
			if (String.IsNullOrEmpty(elementName)) throw new ArgumentNullException("elementName");

			return new XElement(elementName, Normalize(multiString.BestVernacularAnalysisAlternative, mode));
		}
		private static XElement ExportFeatureSystem(IFsFeatureSystem featureSystem, string elementName, Icu.UNormalizationMode mode)
		{
			return new XElement(elementName,
				new XAttribute("Id", featureSystem.Hvo),
				new XElement("Types",
					from type in featureSystem.TypesOC
					 select new XElement("FsFeatStrucType",
						 new XAttribute("Id", type.Hvo),
						 ExportBestAnalysis(type.Name, "Name", mode),
						 ExportBestAnalysis(type.Description, "Description", mode),
						 ExportBestAnalysis(type.Abbreviation, "Abbreviation", mode),
						 new XElement("Features",
							from featureRef in type.FeaturesRS
							select ExportItemAsReference(featureRef, "Feature")))),
				new XElement("Features",
					from featDefn in featureSystem.FeaturesOC
						select ExportFeatureDefn(featDefn, mode)));
		}
Example #27
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Checks all the values of a character in the UnicodeData.txt.
        /// Checks: fields 1-8,11-14
        /// (Skips, 9 and 10, the "Bidi Mirrored" and "Unicode Version 1"
        /// </summary>
        /// <param name="puaIndex"></param><param name="puaName"></param>
        /// <param name="puaGenCat"></param><param name="puaCombiningClass"></param>
        /// <param name="puaBidiClass"></param><param name="puaDecomposition"></param>
        /// <param name="puaNumeric"></param><param name="puaNumericValue"></param>
        /// <param name="puaComment"></param><param name="puaToUpper"></param>
        /// <param name="puaToLower"></param><param name="puaToTitle"></param>
        /// ------------------------------------------------------------------------------------
        public static void Check_PUA(
            int puaIndex,
            string puaName,
            LgGeneralCharCategory puaGenCat,
            int puaCombiningClass,
            LgBidiCategory puaBidiClass,
            string puaDecomposition,
            bool puaNumeric,
            int puaNumericValue,
            string puaComment,
            int puaToUpper,
            int puaToLower,
            int puaToTitle
            )
        {
            string name = "";
            LgGeneralCharCategory genCategory = LgGeneralCharCategory.kccCn;
            int            combiningClass     = 0;
            string         decomposition      = "None";
            LgBidiCategory bidiCategory       = LgBidiCategory.kbicL;
            //string fullDecomp = "I have no clue";
            bool   isNumber     = false;
            int    numericValue = -1;
            int    upper        = -1;
            int    lower        = -1;
            int    title        = -1;
            string comment      = "<none>";

            //Getting the character name at the memory address specified
            ILgCharacterPropertyEngine charPropEngine = LgIcuCharPropEngineClass.Create();

            try
            {
                FwIcu.UErrorCode            error;
                const FwIcu.UCharNameChoice choice = FwIcu.UCharNameChoice.U_UNICODE_CHAR_NAME;
                FwIcu.u_CharName(puaIndex, choice, out name, out error);
                genCategory    = charPropEngine.get_GeneralCategory(puaIndex);
                combiningClass = charPropEngine.get_CombiningClass(puaIndex);
                bidiCategory   = charPropEngine.get_BidiCategory(puaIndex);
                decomposition  = charPropEngine.get_Decomposition(puaIndex);
                //fullDecomp = charPropEngine.get_FullDecomp(puaIndex);
                // Note: isNumber merely checks the General category, it doesn't check to see if there is a valid numeric value.
                isNumber = charPropEngine.get_IsNumber(puaIndex);
                if (isNumber)
                {
                    numericValue = charPropEngine.get_NumericValue(puaIndex);
                }
                comment = charPropEngine.get_Comment(puaIndex);

                upper = charPropEngine.get_ToUpperCh(puaIndex);
                lower = charPropEngine.get_ToLowerCh(puaIndex);
                title = charPropEngine.get_ToTitleCh(puaIndex);
            }
            finally
            {
                // Must release pointer to free memory-mapping before we try to restore files.
                Marshal.ReleaseComObject(charPropEngine);
                charPropEngine = null;
                FwIcu.Cleanup();                                // clean up the ICU files / data
            }

            // StringWriter used to print hexadecimal values in the error messages.
            using (var stringWriter = new StringWriter(new System.Globalization.NumberFormatInfo()))
            {
                string errorMessage = "PUA Character " +
                                      puaIndex.ToString("x", new System.Globalization.NumberFormatInfo()) +
                                      " has an incorrect ";

                //Check Name [1]
                Assert.AreEqual(puaName, name, errorMessage + "name.");

                //Check general category [2]
                Assert.AreEqual(puaGenCat, genCategory, errorMessage + "general category.");

                //Check combining class [3]
                Assert.AreEqual(puaCombiningClass, combiningClass, errorMessage + "combining class.");

                //Check Bidi class [4]
                Assert.AreEqual(puaBidiClass, bidiCategory, errorMessage + "bidi class value.");

                //Check Decomposition [5]
                stringWriter.WriteLine(errorMessage + "decomposition.");
                stringWriter.WriteLine("Decomposition, {0:x}, is incorrect", (int)decomposition[0]);
                Assert.AreEqual(puaDecomposition, decomposition, stringWriter.ToString());

                //Check Numeric Value [6,7,8]
                if (puaNumeric != isNumber)
                {
                    Assert.AreEqual(puaNumeric, isNumber, errorMessage +
                                    "numeric type (i.e. does or doesn't have a numeric value when it should be the other).");
                }
                if (puaNumeric)
                {
                    Assert.AreEqual(puaNumericValue, numericValue, errorMessage + "numeric value.");
                }
                //Check ISO Comment [11]
                Assert.AreEqual(puaComment, comment, errorMessage + "ISO commment");

                //Check uppercase [12]
                stringWriter.Flush();
                stringWriter.WriteLine(errorMessage + "upper case.");
                stringWriter.WriteLine("Found uppercase value: {0:x}", upper);
                Assert.AreEqual(puaToUpper, upper, stringWriter.ToString());
                //Check lowercase [13]
                Assert.AreEqual(puaToLower, lower, errorMessage + "lower case.");
                //Check titlecase [14]
                Assert.AreEqual(puaToTitle, title, errorMessage + "title case.");
            }
        }
		private static XElement ExportSenses(IRepository<ILexSense> senseRepos, Icu.UNormalizationMode mode)
		{
			return new XElement("Senses",
				from sense in senseRepos.AllInstances()
				select new XElement("LexSense",
					new XAttribute("Id", sense.Hvo),
					CreateAttribute("Msa", sense.MorphoSyntaxAnalysisRA),
					ExportBestAnalysis(sense.Gloss, "Gloss", mode),
					ExportBestAnalysis(sense.Definition, "Definition", mode)));
		}
		/// <summary>
		/// Create elements for all PartOfSpeech objects in the owning vector.
		/// </summary>
		private static IEnumerable<XElement> ExportPartsOfSpeechList(IEnumerable<ICmPossibility> partsOfSpeech, Icu.UNormalizationMode mode)
		{
			var retval = new List<XElement>();
			foreach (IPartOfSpeech partOfSpeech in partsOfSpeech)
				ExportPartOfSpeech(partOfSpeech, retval, mode);
			return retval;
		}
		private static XElement ExportAffixtemplate(IMoInflAffixTemplate template, Icu.UNormalizationMode mode)
		{
			return new XElement("MoInflAffixTemplate",
								new XAttribute("Id", template.Hvo),
								new XAttribute("Final", template.Final),
								ExportBestAnalysis(template.Name, "Name", mode),
								ExportBestAnalysis(template.Description, "Description", mode),
								  from slot in template.SlotsRS where IsValidSlot(slot)
								   select ExportItemAsReference(slot, template.SlotsRS.IndexOf(slot), "Slots"),
								  from pfxslot in template.PrefixSlotsRS where IsValidSlot(pfxslot)
								   select ExportItemAsReference(pfxslot, template.PrefixSlotsRS.IndexOf(pfxslot), "PrefixSlots"),
								  from sfxslot in template.SuffixSlotsRS where IsValidSlot(sfxslot)
								   select ExportItemAsReference(sfxslot, template.PrefixSlotsRS.IndexOf(sfxslot), "SuffixSlots"));
		}
		private static XElement ExportAllomorphs(IServiceLocator servLoc, Icu.UNormalizationMode mode)
		{
			return new XElement("Allomorphs",
				from stemAllo in servLoc.GetInstance<IMoStemAllomorphRepository>().AllInstances()
				where stemAllo.Owner.ClassID == LexEntryTags.kClassId
				select new XElement("MoStemAllomorph",
					new XAttribute("Id", stemAllo.Hvo),
					CreateAttribute("MorphType", stemAllo.MorphTypeRA),
					new XAttribute("IsAbstract", stemAllo.IsAbstract ? 1 : 0),
					CreateAttribute("StemName", stemAllo.StemNameRA),
					ExportBestVernacular(stemAllo.Form, "Form", mode),
					from env in stemAllo.PhoneEnvRC
					select ExportItemAsReference(env, "PhoneEnv")),
					from afxAllo in servLoc.GetInstance<IMoAffixAllomorphRepository>().AllInstances()
					where afxAllo.Owner.ClassID == LexEntryTags.kClassId
					select new XElement("MoAffixAllomorph",
						new XAttribute("Id", afxAllo.Hvo),
						CreateAttribute("MorphType", afxAllo.MorphTypeRA),
						new XAttribute("IsAbstract", afxAllo.IsAbstract ? 1 : 0),
						ExportBestVernacular(afxAllo.Form, "Form", mode),
						from env in afxAllo.PhoneEnvRC
						select ExportItemAsReference(env, "PhoneEnv"),
						from position in afxAllo.PositionRS
						select ExportItemAsReference(position, afxAllo.PositionRS.IndexOf(position), "Position"),
						from inflClass in afxAllo.InflectionClassesRC
						select ExportItemAsReference(inflClass, "InflectionClasses"),
						new XElement("MsEnvFeatures", ExportFeatureStructure(afxAllo.MsEnvFeaturesOA))),
					from processAllo in servLoc.GetInstance<IMoAffixProcessRepository>().AllInstances()
					where processAllo.Owner.ClassID == LexEntryTags.kClassId
					select new XElement("MoAffixProcess",
						new XAttribute("Id", processAllo.Hvo),
						CreateAttribute("MorphType", processAllo.MorphTypeRA),
						new XAttribute("IsAbstract", processAllo.IsAbstract ? 1 : 0),
						ExportBestVernacular(processAllo.Form, "Form", mode),
						from inflClass in processAllo.InflectionClassesRC
						select ExportItemAsReference(inflClass, "InflectionClasses"),
						new XElement("Input",
							from context in processAllo.InputOS
							select ExportContext(context)),
						new XElement("Output",
							from mapping in processAllo.OutputOS
							select ExportRuleMapping(mapping)))
				);
		}
		private static string Normalize(string text, Icu.UNormalizationMode mode)
		{
			if (text == null) throw new ArgumentNullException("text");

			return Icu.Normalize(text, mode);
		}
		// ExportMorphTypes rules go above this line.

		private static XElement ExportPhonologicalData(IPhPhonData phonologicalData, Icu.UNormalizationMode mode)
		{
			return new XElement("PhPhonData",
								new XAttribute("Id", phonologicalData.Hvo),
								new XElement("Environments",
									from goodEnvironment in phonologicalData.Services.GetInstance<IPhEnvironmentRepository>().AllValidInstances()
									select new XElement("PhEnvironment",
										new XAttribute("Id", goodEnvironment.Hvo),
										new XAttribute("StringRepresentation",
											Normalize(goodEnvironment.StringRepresentation, mode)),
										CreateAttribute("LeftContext", goodEnvironment.LeftContextRA),
										CreateAttribute("RightContext", goodEnvironment.RightContextRA),
										ExportBestAnalysis(goodEnvironment.Name, "Name", mode),
										ExportBestAnalysis(goodEnvironment.Description, "Description", mode))),
								new XElement("NaturalClasses", from naturalClass in phonologicalData.NaturalClassesOS
																select ExportNaturalClass(naturalClass, mode)),
								new XElement("Contexts", from context in phonologicalData.ContextsOS
														  select ExportContext(context)),
								new XElement("PhonemeSets", from phonemeSet in phonologicalData.PhonemeSetsOS
															 select ExportPhonemeSet(phonemeSet, mode)),
								new XElement("FeatureConstraints", from featureConstraint in phonologicalData.FeatConstraintsOS
																 select ExportFeatureConstraint(featureConstraint)),
								new XElement("PhonRules", from phonRule in phonologicalData.PhonRulesOS
											where !phonRule.Disabled
											select ExportPhonRule(phonRule, mode)),
								ExportPhonRuleFeats(phonologicalData, mode),
							   new XElement("PhIters"),
							   new XElement("PhIters"),
							   new XElement("PhIters"),
							   new XElement("PhIters"),
							   new XElement("PhIters"),
							   new XElement("PhIters"));
		}