/// <summary> /// Perform one increment migration step. /// </summary> /// <param name="domainObjectDtoRepository">Repository of all CmObject DTOs available for one migration step.</param> /// <remarks> /// The method must add/remove/update the DTOs to the repository, /// as it adds/removes objects as part of it work. /// Implementors of this interface should ensure the Repository's /// starting model version number is correct for the step. /// Implementors must also increment the Repository's model version number /// at the end of its migration work. /// The method also should normally modify the xml string(s) /// of relevant DTOs, since that string will be used by the main /// data migration calling client (ie. BEP). /// </remarks> public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) { DataMigrationServices.CheckVersionNumber(domainObjectDtoRepository, 7000018); // collect all writing system info var guidToWsInfo = new Dictionary<string, Tuple<string, DomainObjectDTO, XElement>>(); foreach (DomainObjectDTO wsDto in domainObjectDtoRepository.AllInstancesSansSubclasses("LgWritingSystem").ToArray()) { XElement wsElem = XElement.Parse(wsDto.Xml); XElement icuLocaleElem = wsElem.Element("ICULocale"); var icuLocale = icuLocaleElem.Element("Uni").Value; string langTag = Version19LangTagUtils.ToLangTag(icuLocale); guidToWsInfo[wsDto.Guid.ToLowerInvariant()] = Tuple.Create(langTag, wsDto, wsElem); } // remove all CmSortSpec objects foreach (DomainObjectDTO sortSpecDto in domainObjectDtoRepository.AllInstancesSansSubclasses("CmSortSpec").ToArray()) domainObjectDtoRepository.Remove(sortSpecDto); // remove SortSpecs property from LangProject DomainObjectDTO lpDto = domainObjectDtoRepository.AllInstancesSansSubclasses("LangProject").First(); XElement lpElem = XElement.Parse(lpDto.Xml); XElement sortSpecsElem = lpElem.Element("SortSpecs"); bool lpModified = false; if (sortSpecsElem != null) { sortSpecsElem.Remove(); lpModified = true; } var referencedWsIds = new HashSet<string>(); // convert all LangProject writing system references to strings if (ConvertRefToString(lpElem.Element("AnalysisWss"), guidToWsInfo, referencedWsIds)) lpModified = true; if (ConvertRefToString(lpElem.Element("VernWss"), guidToWsInfo, referencedWsIds)) lpModified = true; if (ConvertRefToString(lpElem.Element("CurAnalysisWss"), guidToWsInfo, referencedWsIds)) lpModified = true; if (ConvertRefToString(lpElem.Element("CurPronunWss"), guidToWsInfo, referencedWsIds)) lpModified = true; if (ConvertRefToString(lpElem.Element("CurVernWss"), guidToWsInfo, referencedWsIds)) lpModified = true; if (lpModified) DataMigrationServices.UpdateDTO(domainObjectDtoRepository, lpDto, lpElem.ToString()); // convert all ReversalIndex writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "ReversalIndex", guidToWsInfo, referencedWsIds); // convert all WordformLookupList writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "WordformLookupList", guidToWsInfo, referencedWsIds); // convert all CmPossibilityList writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "CmPossibilityList", guidToWsInfo, referencedWsIds); // convert all UserViewField writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "UserViewField", guidToWsInfo, referencedWsIds); // convert all CmBaseAnnotation writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "CmBaseAnnotation", guidToWsInfo, referencedWsIds); // convert all FsOpenFeature writing system references to strings ConvertAllRefsToStrings(domainObjectDtoRepository, "FsOpenFeature", guidToWsInfo, referencedWsIds); // convert all ScrMarkerMapping ICU locales to lang tags ConvertAllIcuLocalesToLangTags(domainObjectDtoRepository, "ScrMarkerMapping", referencedWsIds); // convert all ScrImportSource ICU locales to lang tags ConvertAllIcuLocalesToLangTags(domainObjectDtoRepository, "ScrImportSource", referencedWsIds); // convert all ICU locales to Language Tags and remove legacy magic font names foreach (DomainObjectDTO dto in domainObjectDtoRepository.AllInstances()) UpdateStringsAndProps(domainObjectDtoRepository, dto, referencedWsIds); var localStoreFolder = Path.Combine(domainObjectDtoRepository.ProjectFolder, FdoFileHelper.ksWritingSystemsDir); // If any writing systems that project needs don't already exist as LDML files, // create them, either by copying relevant data from a shipping LDML file, or by // extracting data from the obsolete writing system object's XML. if (!string.IsNullOrEmpty(domainObjectDtoRepository.ProjectFolder)) { foreach (Tuple<string, DomainObjectDTO, XElement> wsInfo in guidToWsInfo.Values) { if (referencedWsIds.Contains(wsInfo.Item1)) { var ws = new Version19WritingSystemDefn(); var langTag = wsInfo.Item1; ws.LangTag = langTag; var ldmlFileName = Path.ChangeExtension(langTag, "ldml"); string localPath = Path.Combine(localStoreFolder, ldmlFileName); if (File.Exists(localPath)) continue; // already have one. string globalPath = Path.Combine(DirectoryFinder.GlobalWritingSystemStoreDirectory, ldmlFileName); if (File.Exists(globalPath)) continue; // already have one. // Need to make one. // Code similar to this was in the old migrator (prior to 7000043). It does not work // because the XML files it is looking for are in the Languages subdirectory of the // FieldWorks 6 data directory, and this is looking in the FW 7 one. No one has complained // so we decided not to try to fix it for the new implementation of the migration. //string langDefPath = Path.Combine(FwDirectoryFinder.GetDataSubDirectory("Languages"), // Path.ChangeExtension(langTag, "xml")); //if (File.Exists(langDefPath)) // FillWritingSystemFromLangDef(XElement.Load(langDefPath), ws); //else FillWritingSystemFromFDO(domainObjectDtoRepository, wsInfo.Item3, ws); ws.Save(localPath); } } } foreach (Tuple<string, DomainObjectDTO, XElement> wsInfo in guidToWsInfo.Values) { // this should also remove all LgCollations as well DataMigrationServices.RemoveIncludingOwnedObjects(domainObjectDtoRepository, wsInfo.Item2, false); } DataMigrationServices.IncrementVersionNumber(domainObjectDtoRepository); }
// I think this is roughly what we need to reinstate if we reinstate the call to it. See comments there. //private static void FillWritingSystemFromLangDef(XElement langDefElem, Version19WritingSystemDefn ws) //{ // XElement wsElem = langDefElem.Element("LgWritingSystem"); // if (wsElem != null) // { // string name = GetMultiUnicode(wsElem, "Name24"); // if (!string.IsNullOrEmpty(name)) // { // int parenIndex = name.IndexOf('('); // if (parenIndex != -1) // name = name.Substring(0, parenIndex).Trim(); // ws.LanguageName = name; // } // string abbr = GetMultiUnicode(wsElem, "Abbr24"); // if (!string.IsNullOrEmpty(abbr)) // ws.Abbreviation = abbr; // XElement collsElem = wsElem.Element("Collations24"); // if (collsElem != null) // { // XElement collElem = collsElem.Element("LgCollation"); // if (collElem != null) // { // string icuRules = GetUnicode(collElem, "ICURules30"); // if (!string.IsNullOrEmpty(icuRules)) // { // ws.SortUsing = WritingSystemDefinition.SortRulesType.CustomICU; // ws.SortRules = icuRules; // } // } // } // string defFont = GetUnicode(wsElem, "DefaultSerif24"); // if (!string.IsNullOrEmpty(defFont)) // ws.DefaultFontName = defFont; // string defFontFeats = GetUnicode(wsElem, "FontVariation24"); // if (!string.IsNullOrEmpty(defFontFeats)) // ws.DefaultFontFeatures = defFontFeats; // string keyboard = GetUnicode(wsElem, "KeymanKeyboard24"); // if (!string.IsNullOrEmpty(keyboard)) // ws.Keyboard = keyboard; // string legacyMapping = GetUnicode(wsElem, "LegacyMapping24"); // if (!string.IsNullOrEmpty(legacyMapping)) // ws.LegacyMapping = legacyMapping; // XElement localeElem = wsElem.Element("Locale24"); // if (localeElem != null) // { // XElement intElem = localeElem.Element("Integer"); // if (intElem != null) // ws.LCID = (int) intElem.Attribute("val"); // } // string matchedPairs = GetUnicode(wsElem, "MatchedPairs24"); // if (!string.IsNullOrEmpty(matchedPairs)) // ws.MatchedPairs = matchedPairs; // string punctPatterns = GetUnicode(wsElem, "PunctuationPatterns24"); // if (!string.IsNullOrEmpty(punctPatterns)) // ws.PunctuationPatterns = punctPatterns; // string quotMarks = GetUnicode(wsElem, "QuotationMarks24"); // if (!string.IsNullOrEmpty(quotMarks)) // ws.QuotationMarks = quotMarks; // XElement rtolElem = wsElem.Element("RightToLeft24"); // if (rtolElem != null) // { // XElement boolElem = rtolElem.Element("Boolean"); // if (boolElem != null) // ws.RightToLeftScript = (bool) boolElem.Attribute("val"); // } // string spellCheck = GetUnicode(wsElem, "SpellCheckDictionary24"); // if (!string.IsNullOrEmpty(spellCheck)) // ws.SpellCheckingId = spellCheck; // string validChars = GetUnicode(wsElem, "ValidChars24"); // if (!string.IsNullOrEmpty(validChars)) // ws.ValidChars = Icu.Normalize(validChars, Icu.UNormalizationMode.UNORM_NFD); // } // var localeName = (string) langDefElem.Element("LocaleName"); // if (!string.IsNullOrEmpty(localeName)) // { // ws.LanguageName = localeName; // } // var scriptName = (string)langDefElem.Element("LocaleScript"); // if (!string.IsNullOrEmpty(scriptName)) // { // ws.ScriptName = scriptName; // } // var regionName = (string)langDefElem.Element("LocaleCountry"); // if (!string.IsNullOrEmpty(regionName)) // { // ws.RegionName = regionName; // } // var variantName = (string) langDefElem.Element("LocaleVariant"); // if (!string.IsNullOrEmpty(variantName)) // { // ws.VariantName = variantName; // } //} private static void FillWritingSystemFromFDO(IDomainObjectDTORepository domainObjectDtoRepository, XElement wsElem, Version19WritingSystemDefn ws) { string name = GetMultiUnicode(wsElem, "Name"); if (!string.IsNullOrEmpty(name)) { int parenIndex = name.IndexOf('('); if (parenIndex != -1) name = name.Substring(0, parenIndex).Trim(); ws.LanguageName = name; } string abbr = GetMultiUnicode(wsElem, "Abbr"); if (!string.IsNullOrEmpty(abbr)) ws.Abbreviation = abbr; string defFont = GetUnicode(wsElem, "DefaultSerif"); if (!string.IsNullOrEmpty(defFont)) ws.DefaultFontName = defFont; string defFontFeats = GetUnicode(wsElem, "FontVariation"); if (!string.IsNullOrEmpty(defFontFeats)) ws.DefaultFontFeatures = defFontFeats; string keyboard = GetUnicode(wsElem, "KeymanKeyboard"); if (!string.IsNullOrEmpty(keyboard)) ws.Keyboard = keyboard; string legacyMapping = GetUnicode(wsElem, "LegacyMapping"); if (!string.IsNullOrEmpty(legacyMapping)) ws.LegacyMapping = legacyMapping; XElement localeElem = wsElem.Element("Locale"); if (localeElem != null) ws.LCID = (int) localeElem.Attribute("val"); string matchedPairs = GetUnicode(wsElem, "MatchedPairs"); if (!string.IsNullOrEmpty(matchedPairs)) ws.MatchedPairs = matchedPairs; string puncPatterns = GetUnicode(wsElem, "PunctuationPatterns"); if (!string.IsNullOrEmpty(puncPatterns)) ws.PunctuationPatterns = puncPatterns; string quotMarks = GetUnicode(wsElem, "QuotationMarks"); if (!string.IsNullOrEmpty(quotMarks)) ws.QuotationMarks = quotMarks; XElement rtolElem = wsElem.Element("RightToLeft"); if (rtolElem != null) ws.RightToLeftScript = (bool) rtolElem.Attribute("val"); string spellCheck = GetUnicode(wsElem, "SpellCheckDictionary"); if (!string.IsNullOrEmpty(spellCheck)) ws.SpellCheckingId = spellCheck; string validChars = GetUnicode(wsElem, "ValidChars"); if (!string.IsNullOrEmpty(validChars)) ws.ValidChars = Icu.Normalize(validChars, Icu.UNormalizationMode.UNORM_NFD); XElement collsElem = wsElem.Element("Collations"); if (collsElem != null) { XElement surElem = collsElem.Element("objsur"); if (surElem != null) { var guid = (string) surElem.Attribute("guid"); DomainObjectDTO collDto = domainObjectDtoRepository.GetDTO(guid); XElement collElem = XElement.Parse(collDto.Xml); string sortRules = GetUnicode(collElem, "ICURules"); if (!string.IsNullOrEmpty(sortRules)) { ws.SortUsing = WritingSystemDefinition.SortRulesType.CustomICU; ws.SortRules = sortRules; } } } }