public static ZipDirectory FromArchive(IArchive archive) { ZipDirectory root = new ZipDirectory(); Dictionary<string, ZipDirectory> directories = new Dictionary<string, ZipDirectory> { {"", root} }; foreach (IArchiveEntry entry in archive.Entries) { string entryKey = entry.Key.Trim('/'); string directoryPath = entryKey.Substring(0, entryKey.LastIndexOf('/') + 1); string entryName = entryKey.Substring(entryKey.LastIndexOf('/') + 1); ZipDirectory container = directories[directoryPath]; if (entry.IsDirectory) { ZipDirectory newDirectory = new ZipDirectory(); container.Directories.Add(entryName, newDirectory); directories.Add(entry.Key, newDirectory); } else { container.Files.Add(entryName, entry); } } return root; }
private async Task ReadCollectionFromZip(IArchiveEntry entry, ZipDirectory currentDirectory, string currentPath, Dictionary<string, IArchiveEntry> resourceEntries, Indiagram parent) { using (Stream entryStream = entry.OpenEntryStream()) { XDocument xmlDocument = XDocument.Load(entryStream); XElement rootElement = xmlDocument.Element("indiagram"); if (rootElement != null) { // the current element is an indiagram, just read it await CreateIndiagramFromXml(rootElement, false, parent, async (key, type) => { return await Task.Run(() => { if (resourceEntries.ContainsKey(key)) { return resourceEntries[key].OpenEntryStream(); } throw new IndexOutOfRangeException(string.Format("Key {0} is not available in resources", key)); }); }); } else { // the current element is a category, read it + process its children rootElement = xmlDocument.Element("category"); if (rootElement == null) { return; } Indiagram category = await CreateIndiagramFromXml(rootElement, true, parent, async (key, type) => { return await Task.Run(() => { if (resourceEntries.ContainsKey(key)) { return resourceEntries[key].OpenEntryStream(); } throw new IndexOutOfRangeException(string.Format("Key {0} is not available in resources", key)); }); }); XElement indiagramsElement = rootElement.Element("indiagrams"); if (indiagramsElement == null) { return; } foreach (XElement child in indiagramsElement.Elements("indiagram")) { // look for the entry string directoryName = Path.GetDirectoryName(child.Value); string fileName = Path.GetFileName(child.Value); ZipDirectory directory = GetSubZipDirectory(currentDirectory, currentPath, directoryName); if (directory.Files.ContainsKey(fileName)) { await ReadCollectionFromZip(directory.Files[fileName], directory, directoryName, resourceEntries, category); } else { throw new IndexOutOfRangeException("file names mismatch"); } } } } }
private ZipDirectory GetSubZipDirectory(ZipDirectory current, string currentPath, string expectedPath) { if (string.Equals(currentPath, expectedPath, StringComparison.CurrentCultureIgnoreCase)) { return current; } ZipDirectory sub = GetSubZipDirectory(current, currentPath, Path.GetDirectoryName(expectedPath)); string dirName = Path.GetFileName(expectedPath); if (sub.Directories.ContainsKey(dirName)) { return sub.Directories[dirName]; } throw new IndexOutOfRangeException("directory names mismatch"); }