private void WriteManifest()
        {
            BuildContext   context = this.Context;
            ReferenceGroup group   = this.Group;

            Debug.Assert(context != null);
            Debug.Assert(group != null);
            if (group == null || context == null)
            {
                return;
            }
            BuildGroupContext groupContext = context.GroupContexts[group.Id];

            if (groupContext == null)
            {
                throw new BuildException(
                          "The group context is not provided, and it is required by the build system.");
            }

            string manifestFile = Path.Combine(
                Path.GetDirectoryName(_tocFilePath), groupContext["$ManifestFile"]);

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

            XmlDocument document = new XmlDocument();

            document.Load(manifestFile);
            XPathNavigator documentNavigator = document.CreateNavigator();
            XPathNavigator rootNavigator     =
                documentNavigator.SelectSingleNode("topics");

            if (rootNavigator == null)
            {
                return;
            }

            XmlWriter manifestWriter = rootNavigator.AppendChild();

            // We also save the additional namespaces introduced so that their
            // titles can be changed by changing the <include item="rootTopicTitle"/>,
            // to <include item="namespaceTopicTitle"/> using build components.
            XmlWriterSettings writerSettings = new XmlWriterSettings();

            writerSettings.Indent             = true;
            writerSettings.OmitXmlDeclaration = false;
            writerSettings.Encoding           = Encoding.UTF8;

            string rootNamespaceFile = Path.Combine(context.WorkingDirectory,
                                                    groupContext["$RootNamespaces"]);
            XmlWriter rootWriter = XmlWriter.Create(rootNamespaceFile,
                                                    writerSettings);

            try
            {
                rootWriter.WriteStartDocument();
                rootWriter.WriteStartElement("topics");
                rootWriter.WriteAttributeString("contentsAfter",
                                                _contentsAfter.ToString());

                for (int i = 0; i < _undocumentedNodes.Count; i++)
                {
                    KeyValuePair <string, HierarchicalTocNode> keyValue =
                        _undocumentedNodes[i];
                    HierarchicalTocNode node = keyValue.Value;

                    string topicId = "N:" + node.FullText;

                    manifestWriter.WriteStartElement("topic"); // start: topic
                    manifestWriter.WriteAttributeString("id", topicId);
                    manifestWriter.WriteEndElement();          // end: topic

                    rootWriter.WriteStartElement("topic");     // start: topic
                    rootWriter.WriteAttributeString("id", topicId);

                    if (_dicTocExcludedNamespaces != null &&
                        _dicTocExcludedNamespaces.ContainsKey(topicId))
                    {
                        rootWriter.WriteAttributeString("isTocExcluded",
                                                        "true");
                        string tocExcludedTopic = GetTocExcludedTopic(topicId);
                        string fileName         = String.Empty;
                        if (_namingMethod == ReferenceNamingMethod.Guid)
                        {
                            fileName = ReferenceDocument.GetGuildFileName(
                                tocExcludedTopic);
                        }
                        else if (_namingMethod == ReferenceNamingMethod.MemberName)
                        {
                            fileName = ReferenceDocument.GetFriendlyFileName(
                                tocExcludedTopic);
                        }
                        else
                        {
                            fileName = ReferenceDocument.GetGuildFileName(
                                tocExcludedTopic);
                        }
                        rootWriter.WriteAttributeString("tocExcludedTopic",
                                                        tocExcludedTopic);
                        rootWriter.WriteAttributeString("topicFile",
                                                        fileName);

                        XPathNavigator currNode = rootNavigator.SelectSingleNode(
                            "topic[@id='" + topicId + "']");

                        if (currNode != null && currNode.MoveToAttribute(
                                "id", String.Empty))
                        {
                            currNode.SetValue(tocExcludedTopic);
                            _dicTocExcludedNamespaces[topicId] = fileName;
                        }
                    }

                    rootWriter.WriteEndElement();           // end: topic
                }

                rootWriter.WriteEndElement();
                rootWriter.WriteEndDocument();

                manifestWriter.Close();
                manifestWriter = null;

                rootWriter.Close();
                rootWriter = null;

                document.Save(manifestFile);
            }
            finally
            {
                if (manifestWriter != null)
                {
                    manifestWriter.Close();
                    manifestWriter = null;

                    document.Save(manifestFile);
                }

                if (rootWriter != null)
                {
                    rootWriter.Close();
                    rootWriter = null;
                }
            }
        }
        private void WriteNode(XmlWriter writer, HierarchicalTocNode node)
        {
            if (node == null || String.IsNullOrEmpty(node.Text))
            {
                return;
            }

            string nodeText = node.FullText;
            string topicId  = "N:" + nodeText;

            writer.WriteStartElement("topic");  // start: topic
            writer.WriteAttributeString("id", topicId);

            HierarchicalTocItem tocItem = _tocContents[nodeText];
            string fileName             = String.Empty;
            string projectName          = "_Namespaces";

            if (tocItem != null)
            {
                fileName    = tocItem.FileName;
                projectName = tocItem.ProjectName;
            }
            else
            {
                if (_namingMethod == ReferenceNamingMethod.Guid)
                {
                    fileName = ReferenceDocument.GetGuildFileName(topicId);
                }
                else if (_namingMethod == ReferenceNamingMethod.MemberName)
                {
                    fileName = ReferenceDocument.GetFriendlyFileName(topicId);
                }
                else
                {
                    fileName = ReferenceDocument.GetGuildFileName(topicId);
                }

                _undocumentedNodes.Add(new KeyValuePair <string, HierarchicalTocNode>(
                                           fileName, node));
            }
            writer.WriteAttributeString("project", projectName);
            writer.WriteAttributeString("file", fileName);

            if (!_contentsAfter && (tocItem != null))
            {
                WriteTopics(writer, nodeText);
            }

            if (node.HasChildren)
            {
                IList <HierarchicalTocNode> nodes = node.Children;
                for (int i = 0; i < nodes.Count; i++)
                {
                    this.WriteNode(writer, nodes[i]);
                }
            }

            if (_contentsAfter && (tocItem != null))
            {
                WriteTopics(writer, nodeText);
            }

            writer.WriteEndElement();           // end: topic
        }
        private void WriteReflections()
        {
            BuildGroupContext groupContext = this.Context.GroupContexts[this.Group.Id];

            if (groupContext == null)
            {
                throw new BuildException(
                          "The group context is not provided, and it is required by the build system.");
            }

            string reflectionFile = Path.Combine(
                Path.GetDirectoryName(_tocFilePath), groupContext["$ReflectionFile"]);

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

            XmlDocument document = new XmlDocument();

            document.Load(reflectionFile);
            XPathNavigator documentNavigator = document.CreateNavigator();

            XPathNavigator rootNavigator = documentNavigator.SelectSingleNode(
                "reflection/apis");

            if (rootNavigator == null)
            {
                return;
            }

            XmlWriter writer = rootNavigator.AppendChild();

            for (int i = 0; i < _undocumentedNodes.Count; i++)
            {
                KeyValuePair <string, HierarchicalTocNode> keyValue =
                    _undocumentedNodes[i];
                string fileName          = keyValue.Key;
                HierarchicalTocNode node = keyValue.Value;

                string nodeText = node.FullText;
                string topicId  = "N:" + nodeText;

                // This simulates a root namespace group or container, allowing
                // the transformations to create a list of namespaces with syntax
                // section added. The only issue is that the title include tag is
                // set to <include item="rootTopicTitle"/>, which we can change
                // to <include item="namespaceTopicTitle"/> using build components.
                writer.WriteStartElement("api");       // start: api
                writer.WriteAttributeString("id", topicId);
                writer.WriteStartElement("topicdata"); // start: topicdata
                writer.WriteAttributeString("name", nodeText);
                writer.WriteAttributeString("group", "root");
                writer.WriteEndElement();               // end: topicdata

                writer.WriteStartElement("apidata");    // start: apidata
                writer.WriteAttributeString("name", nodeText);
                writer.WriteAttributeString("group", "namespace");
                writer.WriteEndElement();              // end: apidata

                writer.WriteStartElement("elements");  // start: elements

                XPathNavigator tocExcludedNode = null;

                if (_dicTocExcludedNamespaces != null &&
                    _dicTocExcludedNamespaces.ContainsKey(topicId))
                {
                    tocExcludedNode = rootNavigator.SelectSingleNode(
                        "api[@id='" + topicId + "']");
                    if (tocExcludedNode != null)
                    {
                        string topicFile = _dicTocExcludedNamespaces[topicId];
                        if (!String.IsNullOrEmpty(topicFile))
                        {
                            XPathNavigator fileNode =
                                tocExcludedNode.SelectSingleNode("file");
                            if (fileNode != null && fileNode.MoveToAttribute(
                                    "name", String.Empty))
                            {
                                fileNode.SetValue(topicFile);

                                if (tocExcludedNode.MoveToAttribute("id", String.Empty))
                                {
                                    tocExcludedNode.SetValue(GetTocExcludedTopic(topicId));
                                }
                            }
                        }
                    }
                }

                if (node.HasChildren)
                {
                    IList <HierarchicalTocNode> children = node.Children;
                    for (int j = 0; j < children.Count; j++)
                    {
                        HierarchicalTocNode child = children[j];
                        writer.WriteStartElement("element");  // start: element
                        writer.WriteAttributeString("api", "N:" + child.FullText);
                        writer.WriteEndElement();             // end: element
                    }
                }

                writer.WriteEndElement();         // end: elements

                writer.WriteStartElement("file"); // start: file
                writer.WriteAttributeString("name", fileName);
                writer.WriteEndElement();         // end: file

                writer.WriteEndElement();         // end: api
            }

            writer.Close();

            if (!String.IsNullOrEmpty(_projectName))
            {
                XPathNavigator navigator = rootNavigator.SelectSingleNode(
                    "api[starts-with(@id, 'R:')]");
                if (navigator != null &&
                    navigator.MoveToChild("elements", String.Empty))
                {
                    writer = navigator.AppendChild();

                    for (int i = 0; i < _undocumentedNodes.Count; i++)
                    {
                        KeyValuePair <string, HierarchicalTocNode> keyValue =
                            _undocumentedNodes[i];
                        HierarchicalTocNode node = keyValue.Value;

                        string topicId = "N:" + node.FullText;

                        if (_dicTocExcludedNamespaces != null &&
                            _dicTocExcludedNamespaces.ContainsKey(topicId))
                        {
                            continue;
                        }

                        writer.WriteStartElement("element");  // start: element
                        writer.WriteAttributeString("api", topicId);
                        writer.WriteEndElement();             // end: element
                    }

                    writer.Close();
                }
            }

            document.Save(reflectionFile);
        }
        private bool Visit(string tocFilePath, BuildLogger logger)
        {
            _projectName = String.Empty;
            _projectFile = String.Empty;

            if (String.IsNullOrEmpty(tocFilePath))
            {
                return(false);
            }
            ReferenceTocLayoutType layoutType = _tocLayout.LayoutType;

            if (layoutType == ReferenceTocLayoutType.None ||
                layoutType == ReferenceTocLayoutType.Null ||
                layoutType == ReferenceTocLayoutType.Flat)
            {
                return(false);
            }

            XPathDocument  document          = new XPathDocument(tocFilePath);
            XPathNavigator documentNavigator = document.CreateNavigator();
            XPathNavigator projectNode       = documentNavigator.SelectSingleNode(
                "topics/topic[starts-with(@id, 'R:')]");

            if (projectNode != null)
            {
                _projectName = projectNode.GetAttribute("id", String.Empty);
                if (_projectName == null)
                {
                    _projectName = String.Empty;
                }
                _projectFile = projectNode.GetAttribute("file", String.Empty);
                if (_projectFile == null)
                {
                    _projectFile = String.Empty;
                }
            }

            XPathNavigator rootNode = projectNode;

            if (rootNode == null)
            {
                rootNode = documentNavigator.SelectSingleNode("topics");
            }

            XPathNodeIterator iterator = rootNode.Select(
                "topic[starts-with(@id, 'N:')]");

            if (iterator == null || iterator.Count == 0)
            {
                return(false);
            }

            _undocumentedNodes =
                new List <KeyValuePair <string, HierarchicalTocNode> >();
            _namingMethod = this.EngineSettings.Naming;
            _tocFilePath  = tocFilePath;

            _dicNavigators = new BuildDictionary <XPathNavigator>();

            if (layoutType == ReferenceTocLayoutType.Hierarchical)
            {
                _tocContents = new HierarchicalTocContent();
                _tocContents.BeginItems(_projectName, _projectFile);

                foreach (XPathNavigator navigator in iterator)
                {
                    string nsText = navigator.GetAttribute("id", String.Empty);
                    if (!String.IsNullOrEmpty(nsText) && nsText.Length > 2)
                    {
                        nsText = nsText.Substring(2);
                        string projName = navigator.GetAttribute("project", String.Empty);
                        string fileName = navigator.GetAttribute("file", String.Empty);

                        if (_tocContents.AddItem(nsText, projName, fileName))
                        {
                            _dicNavigators.Add(nsText, navigator.Clone());
                        }
                    }
                }

                _tocContents.EndItems();
            }
            else if (layoutType == ReferenceTocLayoutType.Custom)
            {
                _tocContents = this.Group.Content.HierarchicalToc;

                if (_tocContents != null)
                {
                    foreach (XPathNavigator navigator in iterator)
                    {
                        string nsText = navigator.GetAttribute("id", String.Empty);
                        if (!String.IsNullOrEmpty(nsText) && nsText.Length > 2)
                        {
                            nsText = nsText.Substring(2);
                            string projName = navigator.GetAttribute("project", String.Empty);
                            string fileName = navigator.GetAttribute("file", String.Empty);

                            _dicNavigators.Add(nsText, navigator.Clone());
                        }
                    }
                }
            }

            if (_tocContents == null)
            {
                return(false);
            }

            _rootNode = _tocContents.RootNode;

            return(_rootNode != null);
        }