internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string linguisticsBaseDir)
        {
            var phonologyDir = Path.Combine(linguisticsBaseDir, SharedConstants.Phonology);

            if (!Directory.Exists(phonologyDir))
            {
                return;
            }

            var langProjElement = highLevelData[SharedConstants.LangProject];
            var currentPathname = Path.Combine(phonologyDir, SharedConstants.PhonologyFeaturesFilename);

            if (File.Exists(currentPathname))
            {
                var phoneFeatSysDoc = XDocument.Load(currentPathname);
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    langProjElement, "PhFeatureSystem",
                    phoneFeatSysDoc.Root.Element("FsFeatureSystem"));                     // Owned elment.
            }

            currentPathname = Path.Combine(phonologyDir, SharedConstants.PhonologicalDataFilename);
            if (!File.Exists(currentPathname))
            {
                return;
            }

            var phonDataDoc     = XDocument.Load(currentPathname);
            var phonDataElement = phonDataDoc.Root.Element("PhPhonData");

            BaseDomainServices.RestoreElement(
                currentPathname,
                sortedData,
                langProjElement, "PhonologicalData",
                phonDataElement);                 // Owned elment.

            // Optional PhonRuleFeats list.
            currentPathname = Path.Combine(phonologyDir, SharedConstants.PhonRuleFeaturesFilename);
            if (!File.Exists(currentPathname))
            {
                return;
            }

            var phonRuleFeatsListDoc = XDocument.Load(currentPathname);

            BaseDomainServices.RestoreElement(
                currentPathname,
                sortedData,
                phonDataElement, "PhonRuleFeats",
                phonRuleFeatsListDoc.Root.Element(SharedConstants.CmPossibilityList));                 // Owned elment.
        }
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string linguisticsBaseDir)
        {
            var discourseDir = Path.Combine(linguisticsBaseDir, SharedConstants.DiscourseRootFolder);

            if (!Directory.Exists(discourseDir))
            {
                return;
            }
            var chartPathname = Path.Combine(discourseDir, SharedConstants.DiscourseChartFilename);

            if (!File.Exists(chartPathname))
            {
                return;
            }

            // The charts need to be sorted in guid order, before being added back into the owning prop element.
            var doc              = XDocument.Load(chartPathname);
            var root             = doc.Root;
            var discourseElement = root.Element(SharedConstants.Header).Element("DsDiscourseData");

            // Add lists back into discourseElement.
            foreach (var listPathname in Directory.GetFiles(discourseDir, "*." + SharedConstants.List))
            {
                var listDoc      = XDocument.Load(listPathname);
                var listFilename = Path.GetFileName(listPathname);
                var listElement  = listDoc.Root.Element(SharedConstants.CmPossibilityList);
                switch (listFilename)
                {
                case SharedConstants.ChartMarkersFilename:
                    discourseElement.Element(SharedConstants.ChartMarkers).Add(listElement);
                    break;

                case SharedConstants.ConstChartTemplFilename:
                    discourseElement.Element(SharedConstants.ConstChartTempl).Add(listElement);
                    break;
                }
            }
            // Add the chart elements (except the possible dummy one) into discourseElement.
            var sortedCharts = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);

            foreach (var chartElement in root.Elements(SharedConstants.DsChart)
                     .Where(element => element.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant() != SharedConstants.EmptyGuid))
            {
                // No. Add it to discourseElement, BUT in sorted order, below, and then flatten discourseElement.
                // Restore the right main element name from the class attribute.
                var classAttr = chartElement.Attribute(SharedConstants.Class);
                chartElement.Name = classAttr.Value;
                classAttr.Remove();
                sortedCharts.Add(chartElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), chartElement);
            }

            if (sortedCharts.Count > 0)
            {
                var discourseElementOwningProp = discourseElement.Element("Charts")
                                                 ?? CmObjectFlatteningService.AddNewPropertyElement(discourseElement, "Charts");
                foreach (var sortedChartElement in sortedCharts.Values)
                {
                    discourseElementOwningProp.Add(sortedChartElement);
                }
            }
            var langProjElement = highLevelData[SharedConstants.LangProject];

            BaseDomainServices.RestoreElement(
                chartPathname,
                sortedData,
                langProjElement,
                "DiscourseData",
                discourseElement);
        }
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string linguisticsBaseDir)
        {
            var morphAndSynDir = Path.Combine(linguisticsBaseDir, SharedConstants.MorphologyAndSyntax);

            if (!Directory.Exists(morphAndSynDir))
            {
                return;
            }

            var langProjElement = highLevelData[SharedConstants.LangProject];
            var lexDb           = highLevelData[SharedConstants.LexDb];
            var currentPathname = Path.Combine(morphAndSynDir, SharedConstants.MorphTypesListFilename);

            if (lexDb != null && File.Exists(currentPathname))
            {
                // Restore MorphTypes list to LexDb.
                var morphTypesDoc = XDocument.Load(currentPathname);
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    lexDb, SharedConstants.MorphTypes,
                    morphTypesDoc.Root.Element(SharedConstants.CmPossibilityList));                     // Owned elment.
            }
            var langProjGuid = langProjElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant();

            currentPathname = Path.Combine(morphAndSynDir, SharedConstants.MorphAndSynFeaturesFilename);
            if (File.Exists(currentPathname))
            {
                var mAndSFeatSysDoc = XDocument.Load(currentPathname);
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    langProjElement, "MsFeatureSystem",
                    mAndSFeatSysDoc.Root.Element("FsFeatureSystem"));                     // Owned elment.
            }

            currentPathname = Path.Combine(morphAndSynDir, SharedConstants.PartsOfSpeechFilename);
            if (File.Exists(currentPathname))
            {
                var posDoc = XDocument.Load(currentPathname);
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    langProjElement, SharedConstants.PartsOfSpeech,
                    posDoc.Root.Element(SharedConstants.CmPossibilityList));                     // Owned elment.
            }

            currentPathname = Path.Combine(morphAndSynDir, SharedConstants.AnalyzingAgentsFilename);
            // Put Agents back into LP.
            var sortedAgents = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
            var agentDoc     = XDocument.Load(currentPathname);

            foreach (var agentElement in agentDoc.Root.Elements())
            {
                CmObjectFlatteningService.FlattenOwnedObject(
                    currentPathname,
                    sortedData,
                    agentElement,
                    langProjGuid, sortedAgents);                     // Restore 'ownerguid' to agent.
            }
            // Restore LP AnalyzingAgents property in sorted order.
            if (sortedAgents.Count > 0)
            {
                var langProjOwningProp = langProjElement.Element(SharedConstants.AnalyzingAgents);
                foreach (var sortedTextObjSurElement in sortedAgents.Values)
                {
                    langProjOwningProp.Add(sortedTextObjSurElement);
                }
            }

            currentPathname = Path.Combine(morphAndSynDir, SharedConstants.MorphAndSynDataFilename);
            if (File.Exists(currentPathname))
            {
                var mAndSDataDoc     = XDocument.Load(currentPathname);
                var morphDataElement = mAndSDataDoc.Root.Element("MoMorphData");
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    langProjElement,
                    "MorphologicalData",
                    morphDataElement);

                currentPathname = Path.Combine(morphAndSynDir, "ProdRestrict." + SharedConstants.List);
                if (File.Exists(currentPathname))
                {
                    var prodRestrictDoc         = XDocument.Load(currentPathname);
                    var prodRestrictListElement = prodRestrictDoc.Root.Element(SharedConstants.CmPossibilityList);
                    BaseDomainServices.RestoreElement(
                        currentPathname,
                        sortedData,
                        morphDataElement, "ProdRestrict", prodRestrictListElement);
                }
            }
        }
예제 #4
0
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string linguisticsBaseDir)
        {
            var textCorpusBaseDir = Path.Combine(linguisticsBaseDir, SharedConstants.TextCorpus);

            if (!Directory.Exists(textCorpusBaseDir))
            {
                return;
            }

            var langProjElement = highLevelData[SharedConstants.LangProject];
            var langProjGuid    = langProjElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant();

            // Put the Genre list back in the right place.
            var pathname = Path.Combine(textCorpusBaseDir, SharedConstants.GenreListFilename);
            var doc      = XDocument.Load(pathname);

            BaseDomainServices.RestoreElement(pathname, sortedData, langProjElement, SharedConstants.GenreList, doc.Root.Element(SharedConstants.CmPossibilityList));
            // Put the markup tags list back in the right place.
            pathname = Path.Combine(textCorpusBaseDir, SharedConstants.TextMarkupTagsListFilename);
            doc      = XDocument.Load(pathname);
            BaseDomainServices.RestoreElement(pathname, sortedData, langProjElement, SharedConstants.TextMarkupTags, doc.Root.Element(SharedConstants.CmPossibilityList));
            // Put the translation tags list back in the right place.
            pathname = Path.Combine(textCorpusBaseDir, SharedConstants.TranslationTagsListFilename);
            doc      = XDocument.Load(pathname);
            BaseDomainServices.RestoreElement(pathname, sortedData, langProjElement, SharedConstants.TranslationTags, doc.Root.Element(SharedConstants.CmPossibilityList));

            if (MetadataCache.MdCache.ModelVersion < 7000059)
            {
                // Backwards compatible code.
                // Put Texts back into LP.
                var sortedTexts = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
                foreach (var textPathname in Directory.GetFiles(textCorpusBaseDir, "*." + SharedConstants.TextInCorpus, SearchOption.TopDirectoryOnly))
                {
                    var textDoc = XDocument.Load(textPathname);
                    // Put texts back into index's Entries element.
                    var root        = textDoc.Root;
                    var textElement = root.Elements().First();
                    CmObjectFlatteningService.FlattenOwnedObject(
                        textPathname,
                        sortedData,
                        textElement,
                        langProjGuid, sortedTexts);                         // Restore 'ownerguid' to text.
                }
                // Restore LP Texts property in sorted order.
                if (sortedTexts.Count == 0)
                {
                    return;
                }
                var langProjOwningProp = langProjElement.Element("Texts");
                foreach (var sortedTextObjSurElement in sortedTexts.Values)
                {
                    langProjOwningProp.Add(sortedTextObjSurElement);
                }
            }
            else
            {
                // Put Texts (all unowned now) all in 'sortedData'.
                foreach (var textPathname in Directory.GetFiles(textCorpusBaseDir, "*." + SharedConstants.TextInCorpus, SearchOption.TopDirectoryOnly))
                {
                    var textDoc     = XDocument.Load(textPathname);
                    var root        = textDoc.Root;
                    var textElement = root.Elements().First();
                    CmObjectFlatteningService.FlattenOwnerlessObject(
                        textPathname,
                        sortedData,
                        textElement);
                }
            }
        }
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string linguisticsBaseDir)
        {
            var reversalDir = Path.Combine(linguisticsBaseDir, ReversalRootFolder);

            if (!Directory.Exists(reversalDir))
            {
                return;
            }

            var lexDb          = highLevelData[SharedConstants.LexDb];
            var sortedRevs     = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
            var unlovedFolders = new HashSet <string>();

            foreach (var revIndexDirectoryName in Directory.GetDirectories(reversalDir))
            {
                var dirInfo          = new DirectoryInfo(revIndexDirectoryName);
                var ws               = dirInfo.Name;
                var reversalPathname = Path.Combine(revIndexDirectoryName, ws + "." + SharedConstants.Reversal);
                if (!File.Exists(reversalPathname))
                {
                    // If a reversal is deleted but there were ChorusNotes associated with it the directory might be
                    // here without any reversal files inside it.
                    unlovedFolders.Add(revIndexDirectoryName);
                    continue;
                }

                var reversalDoc = XDocument.Load(reversalPathname);

                // Put entries back into index's Entries element.
                var root          = reversalDoc.Element("Reversal");
                var header        = root.Element(SharedConstants.Header);
                var revIdxElement = header.Element("ReversalIndex");

                // Restore POS list, if it exists.
                var catPathname = Path.Combine(revIndexDirectoryName, ws + "-" + SharedConstants.PartsOfSpeechFilename);
                if (File.Exists(catPathname))
                {
                    var catListDoc = XDocument.Load(catPathname);
                    BaseDomainServices.RestoreElement(
                        catPathname,
                        sortedData,
                        revIdxElement, SharedConstants.PartsOfSpeech,
                        catListDoc.Root.Element(SharedConstants.CmPossibilityList));                         // Owned elment.
                }

                // Put all records back in ReversalIndex, before sort and restore.
                // EXCEPT, if there is only one of them and it is guid.Empty, then skip it
                var sortedRecords = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
                foreach (var recordElement in root.Elements("ReversalIndexEntry")
                         .Where(element => element.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant() != SharedConstants.EmptyGuid))
                {
                    // Add it to Records property of revIdxElement, BUT in sorted order, below, and then flatten dnMainElement.
                    sortedRecords.Add(recordElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), recordElement);
                }

                if (sortedRecords.Count > 0)
                {
                    var recordsElementOwningProp = revIdxElement.Element("Entries")
                                                   ?? CmObjectFlatteningService.AddNewPropertyElement(revIdxElement, "Entries");

                    foreach (var sortedChartElement in sortedRecords.Values)
                    {
                        recordsElementOwningProp.Add(sortedChartElement);
                    }
                }
                CmObjectFlatteningService.FlattenOwnedObject(reversalPathname, sortedData, revIdxElement,
                                                             lexDb.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), sortedRevs); // Restore 'ownerguid' to indices.
            }

            foreach (var unlovedFolder in unlovedFolders)
            {
                Directory.Delete(unlovedFolder, true);
            }

            // Restore lexDb ReversalIndexes property in sorted order.
            if (sortedRevs.Count == 0)
            {
                return;
            }

            var reversalsOwningProp = lexDb.Element("ReversalIndexes") ?? CmObjectFlatteningService.AddNewPropertyElement(lexDb, "ReversalIndexes");

            foreach (var sortedRev in sortedRevs.Values)
            {
                reversalsOwningProp.Add(sortedRev);
            }
        }
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string scriptureBaseDir)
        {
            if (!Directory.Exists(scriptureBaseDir))
            {
                return;
            }

            // scriptureBaseDir is root/Scripture.
            var pathname = Path.Combine(scriptureBaseDir, SharedConstants.ScriptureTransFilename);

            if (!File.Exists(pathname))
            {
                return;                 // Nobody home.
            }
            var doc        = XDocument.Load(pathname);
            var scrElement = doc.Element(SharedConstants.TranslatedScripture).Elements().First();

            // Put the NoteCategories list back in the right place.
            pathname = Path.Combine(scriptureBaseDir, SharedConstants.NoteCategoriesListFilename);
            if (File.Exists(pathname))
            {
                doc = XDocument.Load(pathname);
                BaseDomainServices.RestoreElement(pathname, sortedData, scrElement, SharedConstants.NoteCategories, doc.Root.Element(SharedConstants.CmPossibilityList));
            }

            // Owned by LangProj in TranslatedScripture prop.
            var langProjElement = highLevelData[SharedConstants.LangProject];

            CmObjectFlatteningService.FlattenOwnedObject(
                pathname,
                sortedData,
                scrElement,
                langProjElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(),
                langProjElement, SharedConstants.TranslatedScripture);                 // Restore 'ownerguid' to scrElement.

            // Put the <objsur> elements back into BookAnnotations and ScriptureBooks property elements.
            // There will always be 66 ScrBookAnnotations instances and they need go in canonical book order.
            // There may (or may not) be ScrBook instances, but they all go in canonical book order in ScriptureBooks, if present.
            var booksDir    = Path.Combine(scriptureBaseDir, SharedConstants.Books);
            var sortedFiles = new SortedList <int, string>(66);

            foreach (var pathnameForAnn in Directory.GetFiles(booksDir, "*." + SharedConstants.bookannotations))
            {
                sortedFiles.Add(Int32.Parse(Path.GetFileNameWithoutExtension(pathnameForAnn)), pathnameForAnn);
            }
            var scrElementGuid         = scrElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant();
            var scriptureBooksProperty = scrElement.Element(SharedConstants.ScriptureBooks);

            foreach (var sortedPathnameKvp in sortedFiles)
            {
                var sortedDoc = XDocument.Load(sortedPathnameKvp.Value);
                var element   = sortedDoc.Root.Element(SharedConstants.ScrBookAnnotations);
                CmObjectFlatteningService.FlattenOwnedObject(
                    sortedPathnameKvp.Value,
                    sortedData,
                    element,
                    scrElementGuid, scrElement, SharedConstants.BookAnnotations);                     // Restore 'ownerguid' to annotation.

                // Deal with optional ScrBook
                var bookPathname = sortedPathnameKvp.Value.Replace(SharedConstants.bookannotations, SharedConstants.book);
                if (!File.Exists(bookPathname))
                {
                    continue;
                }

                if (scriptureBooksProperty == null)
                {
                    scriptureBooksProperty = new XElement(SharedConstants.ScriptureBooks);
                    scrElement.Add(scriptureBooksProperty);
                    // Make sure new property is sorted in correct place.
                    DataSortingService.SortMainRtElement(scrElement);
                }
                // Add book <objsur> element to scrElement's ScriptureBooks element.
                sortedDoc = XDocument.Load(bookPathname);
                element   = sortedDoc.Root.Element(SharedConstants.ScrBook);
                CmObjectFlatteningService.FlattenOwnedObject(
                    bookPathname,
                    sortedData,
                    element,
                    scrElementGuid, scrElement, SharedConstants.ScriptureBooks);                     // Restore 'ownerguid' to book.
            }

            highLevelData.Add(scrElement.Attribute(SharedConstants.Class).Value, scrElement);
        }
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string anthropologyBaseDir)
        {
            var langProjElement = highLevelData[SharedConstants.LangProject];
            var currentPathname = Path.Combine(anthropologyBaseDir, SharedConstants.DataNotebookFilename);
            var doc             = XDocument.Load(currentPathname);
            var root            = doc.Root;
            var dnMainElement   = root.Element(SharedConstants.Header).Element("RnResearchNbk");

            // Add the record elements (except the possible dummy one) into dnMainElement.
            var sortedRecords = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);

            foreach (var recordElement in root.Elements("RnGenericRec")
                     .Where(element => element.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant() != SharedConstants.EmptyGuid))
            {
                // Add it to Records property of dnMainElement, BUT in sorted order, below, and then flatten dnMainElement.
                sortedRecords.Add(recordElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), recordElement);
            }

            if (sortedRecords.Count > 0)
            {
                var recordsElementOwningProp = dnMainElement.Element("Records")
                                               ?? CmObjectFlatteningService.AddNewPropertyElement(dnMainElement, "Records");
                foreach (var sortedChartElement in sortedRecords.Values)
                {
                    recordsElementOwningProp.Add(sortedChartElement);
                }
            }

            // Put the RecTypes list back into place in dnMainElement, before dnMainElement is restored.
            // But only as an <objsur> element.
            var recTypesPathname = Path.Combine(anthropologyBaseDir, "RecTypes." + SharedConstants.List);

            if (File.Exists(recTypesPathname))
            {
                var listDoc = XDocument.Load(recTypesPathname);
                BaseDomainServices.RestoreElement(recTypesPathname, sortedData,
                                                  dnMainElement, "RecTypes",
                                                  listDoc.Root.Element(SharedConstants.CmPossibilityList));
            }

            BaseDomainServices.RestoreElement(currentPathname, sortedData,
                                              langProjElement, "ResearchNotebook",
                                              dnMainElement);

            // Put the lists back where they belong in LangProj.
            foreach (var listPathname in Directory.GetFiles(anthropologyBaseDir, "*." + SharedConstants.List))
            {
                var listDoc      = XDocument.Load(listPathname);
                var listRoot     = listDoc.Root;
                var listRootName = listRoot.Name.LocalName;
                if (listRootName == "RecTypes")
                {
                    continue;
                }
                BaseDomainServices.RestoreElement(listPathname,
                                                  sortedData,
                                                  langProjElement,
                                                  listRootName,
                                                  listRoot.Element(SharedConstants.CmPossibilityList));
            }
        }
예제 #8
0
        internal static void FlattenContext(
            SortedDictionary <string, XElement> highLevelData,
            SortedDictionary <string, XElement> sortedData,
            string generalBaseDir)
        {
            var langProjPathname = Path.Combine(generalBaseDir, SharedConstants.LanguageProjectFilename);
            var langProjDoc      = XDocument.Load(langProjPathname);
            var langProjElement  = langProjDoc.Root.Element(SharedConstants.LangProject);

            // Add LP to highLevelData.
            highLevelData.Add(SharedConstants.LangProject, langProjElement);
            // Flatten it.
            CmObjectFlatteningService.FlattenOwnerlessObject(
                langProjPathname,
                sortedData,
                langProjElement);

            // Add stuff LP owns that is here, then flatten it.
            // LP AnnotationDefs (OA-CmPossibilityList).
            var currentPathname = Path.Combine(generalBaseDir, SharedConstants.AnnotationDefsListFilename);

            if (File.Exists(currentPathname))
            {
                // Flatten it here to get the right pathname into the method.
                BaseDomainServices.RestoreElement(
                    currentPathname,
                    sortedData,
                    langProjElement,
                    SharedConstants.AnnotationDefs,
                    XDocument.Load(currentPathname).Root.Element(SharedConstants.CmPossibilityList));
            }

            // LP Styles (OC-StStyle)
            var langProjGuid   = langProjElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant();
            var sortedElements = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);

            currentPathname = Path.Combine(generalBaseDir, SharedConstants.FLExStylesFilename);
            XDocument doc;

            if (File.Exists(currentPathname))
            {
                doc = XDocument.Load(currentPathname);
                foreach (var styleElement in doc.Root.Elements(SharedConstants.StStyle))
                {
                    // Put style back into LP's Styles element.
                    CmObjectFlatteningService.FlattenOwnedObject(
                        currentPathname,
                        sortedData,
                        styleElement,
                        langProjGuid, sortedElements);                         // Restore 'ownerguid' to style.
                }
                // Restore LP Styles property in sorted order.
                var langProjOwningProp = langProjElement.Element(SharedConstants.Styles);
                foreach (var sortedTextObjSurElement in sortedElements.Values)
                {
                    langProjOwningProp.Add(sortedTextObjSurElement);
                }
            }

            // LP Filters (OC-CmFilter)
            currentPathname = Path.Combine(generalBaseDir, SharedConstants.FLExFiltersFilename);
            if (File.Exists(currentPathname))
            {
                sortedElements = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
                doc            = XDocument.Load(currentPathname);
                foreach (var filterElement in doc.Root.Elements("CmFilter"))
                {
                    // Put CmFilter back into LP's Filters element.
                    CmObjectFlatteningService.FlattenOwnedObject(
                        currentPathname,
                        sortedData,
                        filterElement,
                        langProjGuid, sortedElements);                         // Restore 'ownerguid' to style.
                }
                // Restore LP Filters property in sorted order.
                var langProjOwningProp = langProjElement.Element(SharedConstants.Filters);
                foreach (var sortedTextObjSurElement in sortedElements.Values)
                {
                    langProjOwningProp.Add(sortedTextObjSurElement);
                }
            }

            // LP Annotations (OC-CmAnnotation). [Odd elements like in Discourse.]
            currentPathname = Path.Combine(generalBaseDir, SharedConstants.FLExAnnotationsFilename);
            if (File.Exists(currentPathname))
            {
                sortedElements = new SortedDictionary <string, XElement>(StringComparer.OrdinalIgnoreCase);
                doc            = XDocument.Load(currentPathname);
                foreach (var annotationElement in doc.Root.Elements(SharedConstants.CmAnnotation))
                {
                    // Put CmAnnotation back into LP's Annotations element.
                    var classAttr = annotationElement.Attribute(SharedConstants.Class);
                    annotationElement.Name = classAttr.Value;
                    classAttr.Remove();
                    CmObjectFlatteningService.FlattenOwnedObject(
                        currentPathname,
                        sortedData,
                        annotationElement,
                        langProjGuid, sortedElements);                         // Restore 'ownerguid' to style.
                }
                // Restore LP Annotations property in sorted order.
                var owningProp = langProjElement.Element(SharedConstants.Annotations);
                foreach (var sortedTextObjSurElement in sortedElements.Values)
                {
                    owningProp.Add(sortedTextObjSurElement);
                }
            }

            // No VirtualOrdering instances are owned.
            if (MetadataCache.MdCache.ModelVersion > MetadataCache.StartingModelVersion)
            {
                currentPathname = Path.Combine(generalBaseDir, SharedConstants.FLExVirtualOrderingFilename);
                doc             = XDocument.Load(currentPathname);
                foreach (var orderingElement in doc.Root.Elements(SharedConstants.VirtualOrdering))
                {
                    CmObjectFlatteningService.FlattenOwnerlessObject(
                        currentPathname,
                        sortedData,
                        orderingElement);
                }
            }

            // Some CmPicture instances may not be owned.
            currentPathname = Path.Combine(generalBaseDir, SharedConstants.FLExUnownedPicturesFilename);
            doc             = XDocument.Load(currentPathname);
            foreach (var pictureElement in doc.Root.Elements(SharedConstants.CmPicture))
            {
                CmObjectFlatteningService.FlattenOwnerlessObject(
                    currentPathname,
                    sortedData,
                    pictureElement);
            }
        }