Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.Xml-5.5.0/AXmlObject.cs @ 15938

Last change on this file since 15938 was 11804, checked in by jkarder, 10 years ago

#2077:

  • added fancy xml documentation
  • fixed configurations and plattforms
File size: 7.9 KB
Line 
1// Copyright (c) 2009-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Linq;
22using System.Xml;
23using ICSharpCode.NRefactory.Editor;
24using ICSharpCode.NRefactory.Utils;
25
26namespace ICSharpCode.NRefactory.Xml
27{
28  /// <summary>
29  /// XML object. Base class for all nodes in the XML document.
30  /// </summary>
31  public abstract class AXmlObject : ISegment
32  {
33    /// <summary> Empty string.  The namespace used if there is no "xmlns" specified </summary>
34    internal static readonly string NoNamespace = string.Empty;
35   
36    /// <summary> Namespace for "xml:" prefix: "http://www.w3.org/XML/1998/namespace" </summary>
37    public static readonly string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
38   
39    /// <summary> Namesapce for "xmlns:" prefix: "http://www.w3.org/2000/xmlns/" </summary>
40    public static readonly string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
41   
42    readonly AXmlObject parent;
43    internal readonly int startOffset;
44    internal readonly InternalObject internalObject;
45    IList<AXmlObject> children;
46   
47    internal AXmlObject(AXmlObject parent, int startOffset, InternalObject internalObject)
48    {
49      this.parent = parent;
50      this.startOffset = startOffset;
51      this.internalObject = internalObject;
52    }
53   
54    /// <summary>
55    /// Creates an XML reader that reads from this document.
56    /// </summary>
57    /// <remarks>
58    /// The reader will ignore comments and processing instructions; and will not have line information.
59    /// </remarks>
60    public XmlReader CreateReader()
61    {
62      return new AXmlReader(CreateIteratorForReader());
63    }
64   
65    /// <summary>
66    /// Creates an XML reader that reads from this document.
67    /// </summary>
68    /// <param name="settings">Reader settings.
69    /// Currently, only <c>IgnoreComments</c> is supported.</param>
70    /// <remarks>
71    /// The reader will not have line information.
72    /// </remarks>
73    public XmlReader CreateReader(XmlReaderSettings settings)
74    {
75      return new AXmlReader(CreateIteratorForReader(), settings);
76    }
77   
78    /// <summary>
79    /// Creates an XML reader that reads from this document.
80    /// </summary>
81    /// <param name="settings">Reader settings.
82    /// Currently, only <c>IgnoreComments</c> is supported.</param>
83    /// <param name="document">
84    /// The document that was used to parse the XML. It is used to convert offsets to line information.
85    /// </param>
86    public XmlReader CreateReader(XmlReaderSettings settings, IDocument document)
87    {
88      if (document == null)
89        throw new ArgumentNullException("document");
90      return new AXmlReader(CreateIteratorForReader(), settings, document.GetLocation);
91    }
92   
93    /// <summary>
94    /// Creates an XML reader that reads from this document.
95    /// </summary>
96    /// <param name="settings">Reader settings.
97    /// Currently, only <c>IgnoreComments</c> is supported.</param>
98    /// <param name="offsetToTextLocation">
99    /// A function for converting offsets to line information.
100    /// </param>
101    public XmlReader CreateReader(XmlReaderSettings settings, Func<int, TextLocation> offsetToTextLocation)
102    {
103      return new AXmlReader(CreateIteratorForReader(), settings, offsetToTextLocation);
104    }
105   
106    internal virtual ObjectIterator CreateIteratorForReader()
107    {
108      return new ObjectIterator(new[] { internalObject }, startOffset);
109    }
110   
111    /// <summary>
112    /// Gets the parent node.
113    /// </summary>
114    public AXmlObject Parent {
115      get { return parent; }
116    }
117   
118    /// <summary>
119    /// Gets the list of child objects.
120    /// </summary>
121    public IList<AXmlObject> Children {
122      get {
123        var result = LazyInit.VolatileRead(ref this.children);
124        if (result != null) {
125          return result;
126        } else {
127          if (internalObject.NestedObjects != null) {
128            var array = new AXmlObject[internalObject.NestedObjects.Length];
129            for (int i = 0; i < array.Length; i++) {
130              array[i] = internalObject.NestedObjects[i].CreatePublicObject(this, startOffset);
131            }
132            result = Array.AsReadOnly(array);
133          } else {
134            result = EmptyList<AXmlObject>.Instance;
135          }
136          return LazyInit.GetOrSet(ref this.children, result);
137        }
138      }
139    }
140   
141    /// <summary>
142    /// Gets a child fully containg the given offset.
143    /// Goes recursively down the tree.
144    /// Special case if at the end of attribute or text
145    /// </summary>
146    public AXmlObject GetChildAtOffset(int offset)
147    {
148      foreach(AXmlObject child in this.Children) {
149        if (offset == child.EndOffset && (child is AXmlAttribute || child is AXmlText))
150          return child;
151        if (child.StartOffset < offset && offset < child.EndOffset) {
152          return child.GetChildAtOffset(offset);
153        }
154      }
155      return this; // No children at offset
156    }
157   
158    /// <summary>
159    /// The error that occured in the context of this node (excluding nested nodes)
160    /// </summary>
161    public IEnumerable<SyntaxError> MySyntaxErrors {
162      get {
163        if (internalObject.SyntaxErrors != null) {
164          return internalObject.SyntaxErrors.Select(e => new SyntaxError(startOffset + e.RelativeStart, startOffset + e.RelativeEnd, e.Description));
165        } else {
166          return EmptyList<SyntaxError>.Instance;
167        }
168      }
169    }
170   
171    /// <summary>
172    /// The error that occured in the context of this node and all nested nodes.
173    /// It has O(n) cost.
174    /// </summary>
175    public IEnumerable<SyntaxError> SyntaxErrors {
176      get {
177        return TreeTraversal.PreOrder(this, n => n.Children).SelectMany(obj => obj.MySyntaxErrors);
178      }
179    }
180   
181    /// <summary> Get all ancestors of this node </summary>
182    public IEnumerable<AXmlObject> Ancestors {
183      get {
184        AXmlObject curr = this.Parent;
185        while(curr != null) {
186          yield return curr;
187          curr = curr.Parent;
188        }
189      }
190    }
191   
192    #region Helper methods
193   
194    /// <summary> The part of name before ":" </summary>
195    /// <returns> Empty string if not found </returns>
196    internal static string GetNamespacePrefix(string name)
197    {
198      if (string.IsNullOrEmpty(name)) return string.Empty;
199      int colonIndex = name.IndexOf(':');
200      if (colonIndex != -1) {
201        return name.Substring(0, colonIndex);
202      } else {
203        return string.Empty;
204      }
205    }
206   
207    /// <summary> The part of name after ":" </summary>
208    /// <returns> Whole name if ":" not found </returns>
209    internal static string GetLocalName(string name)
210    {
211      if (string.IsNullOrEmpty(name)) return string.Empty;
212      int colonIndex = name.IndexOf(':');
213      if (colonIndex != -1) {
214        return name.Remove(0, colonIndex + 1);
215      } else {
216        return name ?? string.Empty;
217      }
218    }
219   
220    #endregion
221   
222    /// <summary> Call appropriate visit method on the given visitor </summary>
223    public abstract void AcceptVisitor(AXmlVisitor visitor);
224   
225    /// <summary>
226    /// Gets the start offset of the segment.
227    /// </summary>
228    public int StartOffset {
229      get { return startOffset; }
230    }
231   
232    int ISegment.Offset {
233      get { return startOffset; }
234    }
235   
236    /// <inheritdoc/>
237    public int Length {
238      get { return internalObject.Length; }
239    }
240   
241    /// <inheritdoc/>
242    public int EndOffset {
243      get { return startOffset + internalObject.Length; }
244    }
245  }
246}
Note: See TracBrowser for help on using the repository browser.