/Main/Source/HtmlToMaml/TopicCollection.cs
C# | 248 lines | 145 code | 36 blank | 67 comment | 20 complexity | aea6915a06cc24362ebe06c4b04d93a8 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
1//============================================================================= 2// System : HTML to MAML Converter 3// File : TopicCollection.cs 4// Author : Eric Woodruff (Eric@EWoodruff.us) 5// Updated : 09/17/2008 6// Note : Copyright 2008, Eric Woodruff, All rights reserved 7// Compiler: Microsoft Visual C# 8// 9// This file contains a class used to contain a collection of topics. 10// 11// This code is published under the Microsoft Public License (Ms-PL). A copy 12// of the license should be distributed with the code. It can also be found 13// at the project website: http://www.CodePlex.com/SandcastleStyles. This 14// notice, the author's name, and all copyright notices must remain intact in 15// all applications, documentation, and source files. 16// 17// Version Date Who Comments 18// ============================================================================ 19// 1.0.0.0 09/12/2008 EFW Created the code 20//============================================================================= 21 22using System; 23using System.Collections.Generic; 24using System.Collections.ObjectModel; 25using System.IO; 26using System.Xml; 27 28using SandcastleBuilder.Utils; 29 30namespace HtmlToMamlConversion 31{ 32 /// <summary> 33 /// This is a collection of topic items 34 /// </summary> 35 public class TopicCollection : Collection<Topic> 36 { 37 #region Properties 38 //===================================================================== 39 40 /// <summary> 41 /// This is used to get the default topic 42 /// </summary> 43 /// <value>It returns the default topic or null if one is not set</value> 44 public Topic DefaultTopic 45 { 46 get 47 { 48 Topic defaultTopic = null; 49 50 foreach(Topic t in this) 51 { 52 if(t.IsDefaultTopic) 53 defaultTopic = t; 54 else 55 defaultTopic = t.Subtopics.DefaultTopic; 56 57 if(defaultTopic != null) 58 break; 59 } 60 61 return defaultTopic; 62 } 63 } 64 65 /// <summary> 66 /// This is used to get the topic at which the table of content is 67 /// split by the API content. 68 /// </summary> 69 /// <value>This will only be valid if it refers to a root level 70 /// topic. It will return null if a split location has not been 71 /// set at the root level.</value> 72 public Topic SplitTocAtTopic 73 { 74 get 75 { 76 foreach(Topic t in this) 77 if(t.SplitToc) 78 return t; 79 80 return null; 81 } 82 } 83 #endregion 84 85 #region Conversion helpers 86 //===================================================================== 87 88 /// <summary> 89 /// Add all topics from the specified folder recursively to the 90 /// topic collection. 91 /// </summary> 92 /// <param name="folder">The folder from which to get the files</param> 93 /// <param name="topicDictionary">A dictionary used to contain the list 94 /// of files index by name.</param> 95 /// <remarks>Only files with a .htm? or .topic extension are added</remarks> 96 public void AddTopicsFromFolder(string folder, 97 Dictionary<FilePath, Topic> topicDictionary) 98 { 99 Topic topic, removeTopic; 100 FilePath topicPath; 101 string[] files = Directory.GetFiles(folder, "*.htm?"); 102 string name; 103 104 // Add files 105 foreach(string file in files) 106 { 107 topic = new Topic(file); 108 this.Add(topic); 109 topicDictionary.Add(topic.SourceFile, topic); 110 } 111 112 files = Directory.GetFiles(folder, "*.topic"); 113 114 foreach(string file in files) 115 { 116 topic = new Topic(file); 117 this.Add(topic); 118 topicPath = new FilePath(Path.ChangeExtension( 119 topic.SourceFile.Path, ".html"), topic.SourceFile.BasePathProvider); 120 topicDictionary.Add(topicPath, topic); 121 } 122 123 // Add folders recursively 124 files = Directory.GetDirectories(folder); 125 126 foreach(string folderName in files) 127 { 128 topic = new Topic(null); 129 topic.Title = name = Path.GetFileName(folderName); 130 topic.Subtopics.AddTopicsFromFolder(folderName, topicDictionary); 131 132 // Ignore empty folders 133 if(topic.Subtopics.Count == 0) 134 continue; 135 136 this.Add(topic); 137 138 // Look for a file with the same name as the folder 139 removeTopic = null; 140 141 foreach(Topic t in topic.Subtopics) 142 if(t.SourceFile != null && Path.GetFileNameWithoutExtension( 143 t.SourceFile) == name) 144 { 145 // If found, remove it as it represents the container node 146 topic.Title = null; 147 topic.SourceFile = t.SourceFile; 148 topic.Id = t.Id; 149 removeTopic = t; 150 topicDictionary[topic.SourceFile] = topic; 151 break; 152 } 153 154 if(removeTopic != null) 155 topic.Subtopics.Remove(removeTopic); 156 } 157 } 158 159 /// <summary> 160 /// Parse all files in the collection to extract the information for 161 /// conversion. 162 /// </summary> 163 /// <param name="fileParser">The file parser</param> 164 /// <param name="imageDictionary">The image dictionary</param> 165 public void ParseFiles(FileParser fileParser, 166 Dictionary<FilePath, ImageReference> imageDictionary) 167 { 168 foreach(Topic t in this) 169 t.ParseFile(fileParser, imageDictionary); 170 } 171 #endregion 172 173 #region Save to content layout file 174 //===================================================================== 175 176 /// <summary> 177 /// Save the topic collection to the named content layout file 178 /// </summary> 179 /// <param name="filename">The filename to which the content layout 180 /// is saved.</param> 181 public void Save(string filename) 182 { 183 XmlWriterSettings settings = new XmlWriterSettings(); 184 XmlWriter writer = null; 185 Topic defaultTopic = this.DefaultTopic, splitToc = this.SplitTocAtTopic; 186 187 try 188 { 189 this.Sort(); 190 191 settings.Indent = true; 192 settings.CloseOutput = true; 193 writer = XmlWriter.Create(filename, settings); 194 195 writer.WriteStartDocument(); 196 writer.WriteStartElement("Topics"); 197 198 if(defaultTopic != null) 199 writer.WriteAttributeString("defaultTopic", 200 defaultTopic.Id.ToString()); 201 202 if(splitToc != null) 203 writer.WriteAttributeString("splitTOCTopic", 204 splitToc.Id.ToString()); 205 206 foreach(Topic t in this) 207 t.WriteXml(writer); 208 209 writer.WriteEndElement(); 210 writer.WriteEndDocument(); 211 } 212 finally 213 { 214 if(writer != null) 215 writer.Close(); 216 } 217 } 218 #endregion 219 220 #region Sort collection 221 //===================================================================== 222 223 /// <summary> 224 /// This is used to sort the collection 225 /// </summary> 226 /// <remarks>Values are sorted by display title. Comparisons are 227 /// case-sensitive.</remarks> 228 public void Sort() 229 { 230 ((List<Topic>)base.Items).Sort( 231 delegate(Topic x, Topic y) 232 { 233 if(x.SortOrder < y.SortOrder) 234 return -1; 235 236 if(x.SortOrder > y.SortOrder) 237 return 1; 238 239 return String.Compare(x.Title, y.Title, 240 StringComparison.CurrentCultureIgnoreCase); 241 }); 242 243 foreach(Topic t in this) 244 t.Subtopics.Sort(); 245 } 246 #endregion 247 } 248}