You've already forked linux-packaging-mono
Imported Upstream version 5.2.0.179
Former-commit-id: a536d4f20e27294d8bbc2184d75f3a22364f7ba1
This commit is contained in:
parent
966bba02bb
commit
fad71374d0
357
external/api-doc-tools/monodoc/Monodoc/HelpSource.cs
vendored
Normal file
357
external/api-doc-tools/monodoc/Monodoc/HelpSource.cs
vendored
Normal file
@ -0,0 +1,357 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Utilities;
|
||||
using Lucene.Net.Index;
|
||||
|
||||
namespace Monodoc
|
||||
{
|
||||
public enum SortType {
|
||||
Caption,
|
||||
Element
|
||||
}
|
||||
|
||||
//
|
||||
// The HelpSource class keeps track of the archived data, and its
|
||||
// tree
|
||||
//
|
||||
public
|
||||
#if LEGACY_MODE
|
||||
partial
|
||||
#endif
|
||||
class HelpSource
|
||||
{
|
||||
static int id;
|
||||
|
||||
//
|
||||
// The unique ID for this HelpSource.
|
||||
//
|
||||
int source_id;
|
||||
|
||||
// The name of the HelpSource, used by all the file (.tree, .zip, ...) used by it
|
||||
string name;
|
||||
// The full directory path where the HelpSource files are located
|
||||
string basePath;
|
||||
|
||||
// The tree of this help source
|
||||
Tree tree;
|
||||
string treeFilePath;
|
||||
RootTree rootTree;
|
||||
|
||||
IDocCache cache;
|
||||
IDocStorage storage;
|
||||
|
||||
public HelpSource (string base_filename, bool create)
|
||||
{
|
||||
this.name = Path.GetFileName (base_filename);
|
||||
this.basePath = Path.GetDirectoryName (base_filename);
|
||||
this.treeFilePath = base_filename + ".tree";
|
||||
this.storage = new Monodoc.Storage.ZipStorage (base_filename + ".zip");
|
||||
this.cache = DocCacheHelper.GetDefaultCache (Name);
|
||||
|
||||
tree = create ? new Tree (this, string.Empty, string.Empty) : new Tree (this, treeFilePath);
|
||||
|
||||
source_id = id++;
|
||||
}
|
||||
|
||||
public HelpSource ()
|
||||
{
|
||||
tree = new Tree (this, "Blah", "Blah");
|
||||
source_id = id++;
|
||||
this.cache = new Caches.NullCache ();
|
||||
}
|
||||
|
||||
public int SourceID {
|
||||
get {
|
||||
return source_id;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/* This gives the full path of the source/ directory */
|
||||
public string BaseFilePath {
|
||||
get {
|
||||
return basePath;
|
||||
}
|
||||
}
|
||||
|
||||
public TraceLevel TraceLevel {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string BaseDir {
|
||||
get {
|
||||
return basePath;
|
||||
}
|
||||
}
|
||||
|
||||
public Tree Tree {
|
||||
get {
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
||||
public RootTree RootTree {
|
||||
get {
|
||||
return rootTree;
|
||||
}
|
||||
set {
|
||||
rootTree = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IDocCache Cache {
|
||||
get {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
public IDocStorage Storage {
|
||||
get {
|
||||
return storage;
|
||||
}
|
||||
protected set {
|
||||
storage = value;
|
||||
}
|
||||
}
|
||||
|
||||
// A HelpSource may have a common prefix to its URL, give it here
|
||||
protected virtual string UriPrefix {
|
||||
get {
|
||||
return "dummy:";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual SortType SortType {
|
||||
get {
|
||||
return SortType.Caption;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a stream from the packaged help source archive
|
||||
/// </summary>
|
||||
public virtual Stream GetHelpStream (string id)
|
||||
{
|
||||
return storage.Retrieve (id);
|
||||
}
|
||||
|
||||
public virtual Stream GetCachedHelpStream (string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty (id))
|
||||
throw new ArgumentNullException ("id");
|
||||
if (!cache.CanCache (DocEntity.Text))
|
||||
return GetHelpStream (id);
|
||||
if (!cache.IsCached (id))
|
||||
cache.CacheText (id, GetHelpStream (id));
|
||||
return cache.GetCachedStream (id);
|
||||
}
|
||||
|
||||
public XmlReader GetHelpXml (string id)
|
||||
{
|
||||
var url = "monodoc:///" + SourceID + "@" + Uri.EscapeDataString (id) + "@";
|
||||
var stream = cache.IsCached (id) ? cache.GetCachedStream (id) : storage.Retrieve (id);
|
||||
|
||||
return stream == null ? null : new XmlTextReader (url, stream);
|
||||
}
|
||||
|
||||
public virtual XmlDocument GetHelpXmlWithChanges (string id)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument ();
|
||||
if (!storage.SupportRevision) {
|
||||
doc.Load (GetHelpXml (id));
|
||||
} else {
|
||||
var revManager = storage.RevisionManager;
|
||||
doc.Load (revManager.RetrieveLatestRevision (id));
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
public virtual string GetCachedText (string id)
|
||||
{
|
||||
if (!cache.CanCache (DocEntity.Text))
|
||||
return GetText (id);
|
||||
if (!cache.IsCached (id))
|
||||
cache.CacheText (id, GetText (id));
|
||||
return cache.GetCachedString (id);
|
||||
}
|
||||
|
||||
public virtual string GetText (string id)
|
||||
{
|
||||
return new StreamReader (GetHelpStream (id)).ReadToEnd ();
|
||||
}
|
||||
|
||||
// Tells if the result for the provided id is generated dynamically
|
||||
// by the help source
|
||||
public virtual bool IsGeneratedContent (string id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tells if the content of the provided id is meant to be returned raw
|
||||
public virtual bool IsRawContent (string id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tells if provided id refers to a multi-content-type document if it's case
|
||||
// tells the ids it's formed of
|
||||
public virtual bool IsMultiPart (string id, out IEnumerable<string> parts)
|
||||
{
|
||||
parts = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the tree and the archive
|
||||
/// </summary>
|
||||
public void Save ()
|
||||
{
|
||||
tree.Save (treeFilePath);
|
||||
storage.Dispose ();
|
||||
}
|
||||
|
||||
public virtual void RenderPreviewDocs (XmlNode newNode, XmlWriter writer)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public virtual string GetPublicUrl (Node node)
|
||||
{
|
||||
return node.GetInternalUrl ();
|
||||
}
|
||||
|
||||
public virtual bool CanHandleUrl (string url)
|
||||
{
|
||||
return url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public virtual string GetInternalIdForUrl (string url, out Node node, out Dictionary<string, string> context)
|
||||
{
|
||||
context = null;
|
||||
node = MatchNode (url);
|
||||
return node == null ? null : url.Substring (UriPrefix.Length);
|
||||
}
|
||||
|
||||
public virtual Node MatchNode (string url)
|
||||
{
|
||||
Node current = null;
|
||||
|
||||
var matchCache = LRUCache<string, Node>.Default;
|
||||
if ((current = matchCache.Get (url)) != null)
|
||||
return current;
|
||||
|
||||
current = Tree.RootNode;
|
||||
var strippedUrl = url.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? url.Substring (UriPrefix.Length) : url;
|
||||
var searchNode = new Node () { Element = strippedUrl };
|
||||
|
||||
do {
|
||||
int index = current.ChildNodes.BinarySearch (searchNode, NodeElementComparer.Instance);
|
||||
if (index >= 0) {
|
||||
Node n = current.ChildNodes[index];
|
||||
matchCache.Put (url, n);
|
||||
return n;
|
||||
}
|
||||
index = ~index;
|
||||
if (index == current.ChildNodes.Count) {
|
||||
return SlowMatchNode (Tree.RootNode, matchCache, strippedUrl);
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
return null;
|
||||
|
||||
current = current.ChildNodes [index - 1];
|
||||
} while (true);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* That slow path is mainly here to handle ecmaspec type of url which are composed of hard to sort numbers
|
||||
* because they don't have the same amount of digit. We could use a regex to harmonise the various number
|
||||
* parts but then it would be quite specific. Since in the case of ecmaspec the tree is well-formed enough
|
||||
* the "Slow" match should still be fast enough
|
||||
*/
|
||||
Node SlowMatchNode (Node current, LRUCache<string, Node> matchCache, string url)
|
||||
{
|
||||
//Console.WriteLine ("Entering slow path for {0} starting from {1}", url, current.Element);
|
||||
while (current != null) {
|
||||
bool stop = true;
|
||||
foreach (Node n in current.ChildNodes) {
|
||||
var element = n.Element.StartsWith (UriPrefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (UriPrefix.Length) : n.Element;
|
||||
if (url.Equals (element, StringComparison.Ordinal)) {
|
||||
matchCache.Put (url, n);
|
||||
return n;
|
||||
} else if (url.StartsWith (element + ".", StringComparison.OrdinalIgnoreCase) && !n.IsLeaf) {
|
||||
current = n;
|
||||
stop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop)
|
||||
current = null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
class NodeElementComparer : IComparer<Node>
|
||||
{
|
||||
public static NodeElementComparer Instance = new NodeElementComparer ();
|
||||
|
||||
public int Compare (Node n1, Node n2)
|
||||
{
|
||||
return string.Compare (Cleanup (n1), Cleanup (n2), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
string Cleanup (Node n)
|
||||
{
|
||||
var prefix = n.Tree != null && n.Tree.HelpSource != null ? n.Tree.HelpSource.UriPrefix : string.Empty;
|
||||
var element = n.Element.StartsWith (prefix, StringComparison.OrdinalIgnoreCase) ? n.Element.Substring (prefix.Length) : n.Element;
|
||||
if (char.IsDigit (element, 0)) {
|
||||
var count = element.TakeWhile (char.IsDigit).Count ();
|
||||
element = element.PadLeft (Math.Max (0, 3 - count) + element.Length, '0');
|
||||
}
|
||||
//Console.WriteLine ("Cleaned up {0} to {1}", n.Element, element);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual DocumentType GetDocumentTypeForId (string id)
|
||||
{
|
||||
return DocumentType.PlainText;
|
||||
}
|
||||
|
||||
public virtual Stream GetImage (string url)
|
||||
{
|
||||
Stream result = null;
|
||||
storage.TryRetrieve (url, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Populates the index.
|
||||
//
|
||||
public virtual void PopulateIndex (IndexMaker index_maker)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Create different Documents for adding to Lucene search index
|
||||
// The default action is do nothing. Subclasses should add the docs
|
||||
//
|
||||
public virtual void PopulateSearchableIndex (IndexWriter writer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user