private static BCFTopic ReadSingleTopic(ZipArchive archive, string topicId, BCFv2Container container) { var topic = new BCFTopic(); // Get the markup topic.Markup = Markup.Deserialize(archive.Entries.First(e => e.FullName == topicId + "/" + "markup.bcf").Open()); // Check if any comments have a Viewpoint object without any value, then set it to null foreach (var comment in topic.Markup.Comment.Where(c => c.ShouldSerializeViewpoint() && string.IsNullOrWhiteSpace(c.Viewpoint.Guid))) { comment.Viewpoint = null; } if (topic.Markup.Topic.ShouldSerializeBimSnippet() && !topic.Markup.Topic.BimSnippet.isExternal) { // Read the snippet var snippetPathInArchive = GetAbsolutePath(topicId, topic.Markup.Topic.BimSnippet.Reference); var entry = archive.Entries.FirstOrDefault(Curr => Curr.FullName == snippetPathInArchive); if (entry == null) { topic.Markup.Topic.BimSnippet.isExternal = true; } else { using (var memStream = new MemoryStream()) { entry.Open().CopyTo(memStream); topic.SnippetData = memStream.ToArray(); } } } // See if any internal header files are referenced if (topic.Markup.ShouldSerializeHeader() && topic.Markup.Header.Any(h => !h.isExternal)) { foreach (var internalFile in topic.Markup.Header.Where(h => !h.isExternal)) { var filePathInArchive = GetAbsolutePath(topicId, internalFile.Reference); var entry = archive.Entries.FirstOrDefault(e => e.FullName == filePathInArchive); // Only append if not known already and file is present if (entry != null && !container.FileAttachments.ContainsKey(entry.Name)) { using (var memStream = new MemoryStream()) { entry.Open().CopyTo(memStream); container.FileAttachments.Add(entry.Name, memStream.ToArray()); } } } } // Get referenced documents if (topic.Markup.Topic.ShouldSerializeDocumentReferences() && topic.Markup.Topic.DocumentReferences.Any(d => !d.isExternal)) { foreach (var internalDocument in topic.Markup.Topic.DocumentReferences.Where(d => !d.isExternal)) { var filePathInArchive = GetAbsolutePath(topicId, internalDocument.ReferencedDocument); var entry = archive.Entries.FirstOrDefault(e => e.FullName == filePathInArchive); // Only append if not known already and file is present if (entry != null && !container.FileAttachments.ContainsKey(entry.Name)) { using (var memStream = new MemoryStream()) { entry.Open().CopyTo(memStream); container.FileAttachments.Add(entry.Name, memStream.ToArray()); } } } } // Get viewpoints for (var i = 0; i < topic.Markup.Viewpoints.Count; i++) { var deserializedViewpoint = VisualizationInfo.Deserialize(archive.Entries.First(e => e.FullName == topicId + "/" + topic.Markup.Viewpoints[i].Viewpoint).Open()); deserializedViewpoint.GUID = topic.Markup.Viewpoints[i].Guid; topic.Viewpoints.Add(deserializedViewpoint); // Get viewpoint bitmaps if present if (topic.Viewpoints[i].Bitmaps.Count > 0) { foreach (var viewpointBitmap in topic.Viewpoints[i].Bitmaps) { using (var bytesMemoryStream = new MemoryStream()) { var bitmapPathInArchive = GetAbsolutePath(topicId, viewpointBitmap.Reference); var bitmapFileEntry = archive.Entries.FirstOrDefault(e => e.FullName == bitmapPathInArchive); if (bitmapFileEntry == null) { // File entry was not found, possible because it was referenced with an absolute path bitmapPathInArchive = GetAbsolutePath(topicId, TransformToRelativePath(viewpointBitmap.Reference, topicId)); bitmapFileEntry = archive.Entries.FirstOrDefault(e => e.FullName == bitmapPathInArchive); if (bitmapFileEntry != null) { viewpointBitmap.Reference = TransformToRelativePath(viewpointBitmap.Reference, topicId); } else { throw new ArgumentNullException(nameof(bitmapFileEntry), "Could not locate bitmap file in archive"); } } bitmapFileEntry.Open().CopyTo(bytesMemoryStream); if (!topic.ViewpointBitmaps.ContainsKey(topic.Viewpoints[i])) { topic.ViewpointBitmaps.Add(topic.Viewpoints[i], new List <byte[]>()); } topic.ViewpointBitmaps[topic.Viewpoints[i]].Add(bytesMemoryStream.ToArray()); } } } if (!string.IsNullOrWhiteSpace(topic.Markup.Viewpoints[i].Snapshot)) { using (var bytesMemoryStream = new MemoryStream()) { archive.Entries.First(e => e.FullName == topicId + "/" + topic.Markup.Viewpoints[i].Snapshot).Open().CopyTo(bytesMemoryStream); topic.AddOrUpdateSnapshot(topic.Viewpoints[i].GUID, bytesMemoryStream.ToArray()); } } } return(topic); }