internal static void NestContext(string linguisticsBaseDir,
                                         IDictionary <string, XElement> wellUsedElements,
                                         IDictionary <string, SortedDictionary <string, byte[]> > classData,
                                         Dictionary <string, string> guidToClassMapping)
        {
            var sortedPunctuationFormInstanceData = classData["PunctuationForm"];
            var sortedWfiWordformInstanceData     = classData["WfiWordform"];

            var inventoryDir = Path.Combine(linguisticsBaseDir, SharedConstants.WordformInventoryRootFolder);

            if (!Directory.Exists(inventoryDir))
            {
                Directory.CreateDirectory(inventoryDir);
            }

            // the doc root will be "Inventory" (SharedConstants.WordformInventoryRootFolder).
            // This will store the PunctuationForm instances (unowned) in the header, and each PunctuationForm will be a child of header.
            // Each WfiWordform (unowned) will then be a child of root.
            var header = new XElement(SharedConstants.Header);
            // Work on copy, since 'classData' is changed during the loop.
            SortedDictionary <string, byte[]> srcDataCopy;

            if (sortedPunctuationFormInstanceData.Count > 0)
            {
                // There may be no punct forms, even if there are wordforms, so header really is optional.
                srcDataCopy = new SortedDictionary <string, byte[]>(sortedPunctuationFormInstanceData);
                foreach (var punctFormStringData in srcDataCopy.Values)
                {
                    var pfElement = Utilities.CreateFromBytes(punctFormStringData);
                    header.Add(pfElement);
                    CmObjectNestingService.NestObject(false,
                                                      pfElement,
                                                      classData,
                                                      guidToClassMapping);
                }
            }

            var nestedData = new SortedDictionary <string, XElement>();

            if (sortedWfiWordformInstanceData.Count > 0)
            {
                // Work on copy, since 'classData' is changed during the loop.
                srcDataCopy = new SortedDictionary <string, byte[]>(sortedWfiWordformInstanceData);
                foreach (var wordFormElement in srcDataCopy.Values)
                {
                    var wfElement        = Utilities.CreateFromBytes(wordFormElement);
                    var checksumProperty = wfElement.Element("Checksum");
                    if (checksumProperty != null)
                    {
                        // Can be null, for DMs less than 64.
                        checksumProperty.Attribute(SharedConstants.Val).Value = "0";
                    }
                    CmObjectNestingService.NestObject(false,
                                                      wfElement,
                                                      classData,
                                                      guidToClassMapping);
                    nestedData.Add(wfElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), wfElement);
                }
            }

            var buckets = FileWriterService.CreateEmptyBuckets(10);

            FileWriterService.FillBuckets(buckets, nestedData);

            for (var i = 0; i < buckets.Count; ++i)
            {
                var root = new XElement(SharedConstants.WordformInventoryRootFolder);
                if (i == 0 && header.HasElements)
                {
                    root.Add(header);
                }
                var currentBucket = buckets[i];
                foreach (var wordform in currentBucket.Values)
                {
                    root.Add(wordform);
                }
                FileWriterService.WriteNestedFile(PathnameForBucket(inventoryDir, i), root);
            }
        }
        internal static void NestContext(string linguisticsBaseDir,
                                         IDictionary <string, XElement> wellUsedElements,
                                         IDictionary <string, SortedDictionary <string, byte[]> > classData,
                                         Dictionary <string, string> guidToClassMapping)
        {
            var lexiconDir = Path.Combine(linguisticsBaseDir, SharedConstants.Lexicon);

            if (!Directory.Exists(lexiconDir))
            {
                Directory.CreateDirectory(lexiconDir);
            }

            var lexDb = wellUsedElements[SharedConstants.LexDb];             // It has had its "ReversalIndexes" property processed already, so it should be an empty element.
            // lexDb is owned by the LP in its LexDb property, so remove its <objsur> node.
            var langProjElement = wellUsedElements[SharedConstants.LangProject];

            langProjElement.Element(SharedConstants.LexDb).RemoveNodes();

            // Nest each CmPossibilityList owned by LexDb.
            var lists = classData[SharedConstants.CmPossibilityList];

            NestLists(classData, guidToClassMapping, lists, lexiconDir, lexDb,
                      new List <string>
            {
                "SenseTypes",
                "UsageTypes",
                "DomainTypes",
                // Moved to Morph & Syn, as per AndyB. "MorphTypes",
                "References",
                "VariantEntryTypes",
                "ComplexEntryTypes",
                "Languages",
                "DialectLabels",
                "ExtendedNoteTypes",
                "PublicationTypes"
            });

            // Nest SemanticDomainList and AffixCategories props of LangProject.
            NestLists(classData, guidToClassMapping, lists, lexiconDir, langProjElement,
                      new List <string>
            {
                "SemanticDomainList",
                "AffixCategories"
            });

            // The LexDb object will go into the <header>, and will still nest these owning props: Appendixes, Introduction, and Resources (plus its basic props).
            // All of the lexical entries will then go in as siblings of, but after, the <header> element.
            // At this point LexDb is ready to go into the <header>.
            CmObjectNestingService.NestObject(false, lexDb,
                                              classData,
                                              guidToClassMapping);
            var header = new XElement(SharedConstants.Header);

            header.Add(lexDb);

            var sortedEntryInstanceData = classData[SharedConstants.LexEntry];
            var nestedData = new SortedDictionary <string, XElement>();

            if (sortedEntryInstanceData.Count > 0)
            {
                var srcDataCopy = new SortedDictionary <string, byte[]>(sortedEntryInstanceData);
                foreach (var entry in srcDataCopy.Values)
                {
                    var entryElement = Utilities.CreateFromBytes(entry);
                    CmObjectNestingService.NestObject(false, entryElement,
                                                      classData,
                                                      guidToClassMapping);
                    nestedData.Add(entryElement.Attribute(SharedConstants.GuidStr).Value.ToLowerInvariant(), entryElement);
                }
            }

            var buckets = FileWriterService.CreateEmptyBuckets(10);

            FileWriterService.FillBuckets(buckets, nestedData);

            for (var i = 0; i < buckets.Count; ++i)
            {
                var root = new XElement(SharedConstants.Lexicon);
                if (i == 0 && header.HasElements)
                {
                    root.Add(header);
                }
                var currentBucket = buckets[i];
                foreach (var entry in currentBucket.Values)
                {
                    root.Add(entry);
                }
                FileWriterService.WriteNestedFile(PathnameForBucket(lexiconDir, i), root);
            }
        }