[NUI] remove "_" and refactoring naming to pascal case.
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Xaml / XamlNode.cs
1 using System.Collections.Generic;
2 using System.Diagnostics;
3 using System.Linq;
4 using System.Xml;
5 using Tizen.NUI.Binding;
6 using Tizen.NUI.Binding.Internals;
7
8 namespace Tizen.NUI.Xaml
9 {
10     internal interface INode
11     {
12         List<string> IgnorablePrefixes { get; set; }
13
14         IXmlNamespaceResolver NamespaceResolver { get; }
15
16         INode Parent { get; set; }
17
18         void Accept(IXamlNodeVisitor visitor, INode parentNode);
19         INode Clone();
20     }
21
22     internal interface IValueNode : INode
23     {
24     }
25
26     internal interface IElementNode : INode, IListNode
27     {
28         Dictionary<XmlName, INode> Properties { get; }
29         List<XmlName> SkipProperties { get; }
30         INameScope Namescope { get; }
31         XmlType XmlType { get; }
32         string NamespaceURI { get; }
33     }
34
35     internal interface IListNode : INode
36     {
37         List<INode> CollectionItems { get; }
38     }
39
40     [DebuggerDisplay("{NamespaceUri}:{Name}")]
41     internal class XmlType
42     {
43         public XmlType(string namespaceUri, string name, IList<XmlType> typeArguments)
44         {
45             NamespaceUri = namespaceUri;
46             Name = name;
47             TypeArguments = typeArguments;
48         }
49
50         public string NamespaceUri { get; }
51         public string Name { get; }
52         public IList<XmlType> TypeArguments { get; }
53     }
54
55     internal abstract class BaseNode : IXmlLineInfo, INode
56     {
57         protected BaseNode(IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
58         {
59             NamespaceResolver = namespaceResolver;
60             LineNumber = linenumber;
61             LinePosition = lineposition;
62         }
63
64         public IXmlNamespaceResolver NamespaceResolver { get; }
65         public INode Parent { get; set; }
66         public List<string> IgnorablePrefixes { get; set; }
67         public int LineNumber { get; set; }
68         public int LinePosition { get; set; }
69
70         public bool HasLineInfo() => LineNumber >= 0 && LinePosition >= 0;
71
72         public abstract void Accept(IXamlNodeVisitor visitor, INode parentNode);
73         public abstract INode Clone();
74     }
75
76     [DebuggerDisplay("{Value}")]
77     internal class ValueNode : BaseNode, IValueNode
78     {
79         public ValueNode(object value, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
80             : base(namespaceResolver, linenumber, lineposition)
81         {
82             Value = value;
83         }
84
85         public object Value { get; set; }
86
87         public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
88         {
89             visitor.Visit(this, parentNode);
90         }
91
92         public override INode Clone() => new ValueNode(Value, NamespaceResolver, LineNumber, LinePosition)
93         {
94             IgnorablePrefixes = IgnorablePrefixes
95         };
96     }
97
98     [DebuggerDisplay("{MarkupString}")]
99     internal class MarkupNode : BaseNode, IValueNode
100     {
101         public MarkupNode(string markupString, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
102             : base(namespaceResolver, linenumber, lineposition)
103         {
104             MarkupString = markupString;
105         }
106
107         public string MarkupString { get; }
108
109         public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
110         {
111             visitor.Visit(this, parentNode);
112         }
113
114         public override INode Clone() => new MarkupNode(MarkupString, NamespaceResolver, LineNumber, LinePosition)
115         {
116             IgnorablePrefixes = IgnorablePrefixes
117         };
118     }
119
120     [DebuggerDisplay("{XmlType.Name}")]
121     internal class ElementNode : BaseNode, IValueNode, IElementNode
122     {
123         public ElementNode(XmlType type, string namespaceURI, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
124             int lineposition = -1)
125             : base(namespaceResolver, linenumber, lineposition)
126         {
127             Properties = new Dictionary<XmlName, INode>();
128             SkipProperties = new List<XmlName>();
129             CollectionItems = new List<INode>();
130             XmlType = type;
131             NamespaceURI = namespaceURI;
132         }
133
134         public Dictionary<XmlName, INode> Properties { get; }
135         public List<XmlName> SkipProperties { get; }
136         public List<INode> CollectionItems { get; }
137         public XmlType XmlType { get; }
138         public string NamespaceURI { get; }
139         public INameScope Namescope { get; set; }
140
141         public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
142         {
143             if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
144                 visitor.Visit(this, parentNode);
145
146             if (!SkipChildren(visitor, this, parentNode))
147             {
148                 foreach (var node in Properties.Values.ToList())
149                     node.Accept(visitor, this);
150                 foreach (var node in CollectionItems)
151                     node.Accept(visitor, this);
152             }
153
154             if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
155                 visitor.Visit(this, parentNode);
156
157         }
158
159         bool IsDataTemplate(INode parentNode)
160         {
161             var parentElement = parentNode as IElementNode;
162             INode createContent;
163             if (parentElement != null &&
164                 parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
165                 createContent == this)
166                 return true;
167             return false;
168         }
169
170         protected bool SkipChildren(IXamlNodeVisitor visitor, INode node, INode parentNode) =>
171                (visitor.StopOnDataTemplate && IsDataTemplate(parentNode))
172             || (visitor.StopOnResourceDictionary && visitor.IsResourceDictionary(this))
173             || visitor.SkipChildren(node, parentNode);
174
175         protected bool SkipVisitNode(IXamlNodeVisitor visitor, INode parentNode) =>
176             !visitor.VisitNodeOnDataTemplate && IsDataTemplate(parentNode);
177
178         public override INode Clone()
179         {
180             var clone = new ElementNode(XmlType, NamespaceURI, NamespaceResolver, LineNumber, LinePosition)
181             {
182                 IgnorablePrefixes = IgnorablePrefixes
183             };
184             foreach (var kvp in Properties)
185                 clone.Properties.Add(kvp.Key, kvp.Value.Clone());
186             foreach (var p in SkipProperties)
187                 clone.SkipProperties.Add(p);
188             foreach (var p in CollectionItems)
189                 clone.CollectionItems.Add(p.Clone());
190             return clone;
191         }
192     }
193
194     internal abstract class RootNode : ElementNode
195     {
196         protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver) : base(xmlType, xmlType.NamespaceUri, nsResolver)
197         {
198         }
199
200         public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
201         {
202             if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
203                 visitor.Visit(this, parentNode);
204
205             if (!SkipChildren(visitor, this, parentNode))
206             {
207                 foreach (var node in Properties.Values.ToList())
208                     node.Accept(visitor, this);
209                 foreach (var node in CollectionItems)
210                     node.Accept(visitor, this);
211             }
212
213             if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
214                 visitor.Visit(this, parentNode);
215         }
216     }
217
218     internal class ListNode : BaseNode, IListNode, IValueNode
219     {
220         public ListNode(IList<INode> nodes, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
221             : base(namespaceResolver, linenumber, lineposition)
222         {
223             CollectionItems = nodes.ToList();
224         }
225
226         public XmlName XmlName { get; set; }
227         public List<INode> CollectionItems { get; set; }
228
229         public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
230         {
231             if (visitor.VisitingMode == TreeVisitingMode.TopDown)
232                 visitor.Visit(this, parentNode);
233             foreach (var node in CollectionItems)
234                 node.Accept(visitor, this);
235             if (visitor.VisitingMode == TreeVisitingMode.BottomUp)
236                 visitor.Visit(this, parentNode);
237         }
238
239         public override INode Clone()
240         {
241             var items = new List<INode>();
242             foreach (var p in CollectionItems)
243                 items.Add(p.Clone());
244             return new ListNode(items, NamespaceResolver, LineNumber, LinePosition)
245             {
246                 IgnorablePrefixes = IgnorablePrefixes
247             };
248         }
249     }
250
251     internal static class INodeExtensions
252     {
253         public static bool SkipPrefix(this INode node, string prefix)
254         {
255             do
256             {
257                 if (node.IgnorablePrefixes != null && node.IgnorablePrefixes.Contains(prefix))
258                     return true;
259                 node = node.Parent;
260             } while (node != null);
261             return false;
262         }
263     }
264 }