Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XmlScriptElement.cs
1using System.Collections.Generic;
2using System.Threading.Tasks;
3using System.Xml;
7
9{
14 {
15 private XmlScriptAttribute xmlns;
16 private readonly XmlScriptAttribute[] attributes;
17 private LinkedList<XmlScriptNode> children = null;
18 private readonly string name;
19 private readonly int nrAttributes;
20 private bool isAsync;
21
31 public XmlScriptElement(string Name, XmlScriptAttribute Xmlns, XmlScriptAttribute[] Attributes,
33 : base(Start, Length, Expression)
34 {
35 this.name = Name;
36
37 this.xmlns = Xmlns;
38 this.xmlns?.SetParent(this);
39
40 this.attributes = Attributes;
41 this.attributes?.SetParent(this);
42
43 this.nrAttributes = Attributes.Length;
44
45 this.CalcIsAsync();
46 }
47
48 private void CalcIsAsync()
49 {
50 this.isAsync = this.xmlns?.IsAsynchronous ?? false;
51 if (this.isAsync)
52 return;
53
54 for (int i = 0; i < this.nrAttributes; i++)
55 {
56 if (this.attributes[i]?.IsAsynchronous ?? false)
57 {
58 this.isAsync = true;
59 break;
60 }
61 }
62
63 LinkedListNode<XmlScriptNode> Loop = this.children?.First;
64 while (!(Loop is null))
65 {
66 if (Loop.Value?.IsAsynchronous ?? false)
67 {
68 this.isAsync = true;
69 return;
70 }
71 else
72 Loop = Loop.Next;
73 }
74 }
75
80 public override bool IsAsynchronous => this.isAsync;
81
86 public void Add(XmlScriptNode Node)
87 {
88 if (this.children is null)
89 this.children = new LinkedList<XmlScriptNode>();
90
91 this.children.AddLast(Node);
92 Node?.SetParent(this);
93
94 this.isAsync |= Node?.IsAsynchronous ?? false;
95 }
96
104 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
105 {
106 LinkedListNode<XmlScriptNode> Loop;
107 int i;
108
109 if (Order == SearchMethod.DepthFirst)
110 {
111 if (!(this.xmlns?.ForAllChildNodes(Callback, State, Order) ?? true))
112 return false;
113
114 for (i = 0; i < this.nrAttributes; i++)
115 {
116 if (!this.attributes[i].ForAllChildNodes(Callback, State, Order))
117 return false;
118 }
119
120 Loop = this.children?.First;
121 while (!(Loop is null))
122 {
123 if (!Loop.Value.ForAllChildNodes(Callback, State, Order))
124 return false;
125
126 Loop = Loop.Next;
127 }
128 }
129
130 ScriptNode NewNode;
131 bool RecalcIsAsync = false;
132 bool b;
133
134 if (!(this.xmlns is null))
135 {
136 b = !Callback(this.xmlns, out NewNode, State);
137 if (!(NewNode is null) && NewNode is XmlScriptAttribute NewAttr)
138 {
139 this.xmlns = NewAttr;
140 this.xmlns.SetParent(this);
141
142 RecalcIsAsync = true;
143 }
144
145 if (b || (Order == SearchMethod.TreeOrder && !this.xmlns.ForAllChildNodes(Callback, State, Order)))
146 {
147 if (RecalcIsAsync)
148 this.CalcIsAsync();
149
150 return false;
151 }
152 }
153
154 for (i = 0; i < this.nrAttributes; i++)
155 {
156 b = !Callback(this.attributes[i], out NewNode, State);
157 if (!(NewNode is null) && NewNode is XmlScriptAttribute Attr)
158 {
159 this.attributes[i] = Attr;
160 Attr.SetParent(this);
161
162 RecalcIsAsync = true;
163 }
164
165 if (b || (Order == SearchMethod.TreeOrder && !this.attributes[i].ForAllChildNodes(Callback, State, Order)))
166 {
167 if (RecalcIsAsync)
168 this.CalcIsAsync();
169
170 return false;
171 }
172 }
173
174 Loop = this.children?.First;
175 while (!(Loop is null))
176 {
177 b = !Callback(Loop.Value, out NewNode, State);
178 if (!(NewNode is null) && NewNode is XmlScriptNode Node2)
179 {
180 Loop.Value = Node2;
181 Node2.SetParent(this);
182
183 RecalcIsAsync = true;
184 }
185
186 if (b || (Order == SearchMethod.TreeOrder && !Loop.Value.ForAllChildNodes(Callback, State, Order)))
187 {
188 if (RecalcIsAsync)
189 this.CalcIsAsync();
190
191 return false;
192 }
193
194 Loop = Loop.Next;
195 }
196
197 if (RecalcIsAsync)
198 this.CalcIsAsync();
199
200 if (Order == SearchMethod.BreadthFirst)
201 {
202 if (!(this.xmlns?.ForAllChildNodes(Callback, State, Order) ?? true))
203 return false;
204
205 for (i = 0; i < this.nrAttributes; i++)
206 {
207 if (!this.attributes[i].ForAllChildNodes(Callback, State, Order))
208 return false;
209 }
210
211 Loop = this.children?.First;
212 while (!(Loop is null))
213 {
214 if (!Loop.Value.ForAllChildNodes(Callback, State, Order))
215 return false;
216
217 Loop = Loop.Next;
218 }
219 }
220
221 return true;
222 }
223
230 internal override void Build(XmlDocument Document, XmlElement Parent, Variables Variables)
231 {
232 string ns = this.xmlns?.GetValue(Variables) ?? null;
233 XmlElement E;
234
235 if (ns is null)
236 {
237 if (Parent is null || string.IsNullOrEmpty(ns = Parent.NamespaceURI))
238 {
239 if (Variables.TryGetVariable(XmlScriptValue.ParentNamespaceVariableName, out Variable v) && v.ValueObject is string s)
240 ns = s;
241 }
242
243 if (string.IsNullOrEmpty(ns))
244 E = Document.CreateElement(this.name);
245 else
246 E = Document.CreateElement(this.name, ns);
247 }
248 else
249 E = Document.CreateElement(this.name, ns);
250
251 if (Parent is null)
252 Document.AppendChild(E);
253 else
254 Parent.AppendChild(E);
255
256 foreach (XmlScriptAttribute Attr in this.attributes)
257 Attr.Build(Document, E, Variables);
258
259 if (!(this.children is null))
260 {
261 foreach (XmlScriptNode Node in this.children)
262 Node.Build(Document, E, Variables);
263 }
264 }
265
272 internal override async Task BuildAsync(XmlDocument Document, XmlElement Parent, Variables Variables)
273 {
274 if (!this.isAsync)
275 {
276 this.Build(Document, Parent, Variables);
277 return;
278 }
279
280 string ns;
281 XmlElement E;
282
283 if (this.xmlns is null)
284 ns = null;
285 else
286 ns = await this.xmlns.GetValueAsync(Variables);
287
288 if (ns is null)
289 {
290 if (Parent is null || string.IsNullOrEmpty(ns = Parent.NamespaceURI))
291 {
292 if (Variables.TryGetVariable(XmlScriptValue.ParentNamespaceVariableName, out Variable v) && v.ValueObject is string s)
293 ns = s;
294 }
295
296 if (string.IsNullOrEmpty(ns))
297 E = Document.CreateElement(this.name);
298 else
299 E = Document.CreateElement(this.name, ns);
300 }
301 else
302 E = Document.CreateElement(this.name, ns);
303
304 if (Parent is null)
305 Document.AppendChild(E);
306 else
307 Parent.AppendChild(E);
308
309 foreach (XmlScriptAttribute Attr in this.attributes)
310 await Attr.BuildAsync(Document, E, Variables);
311
312 if (!(this.children is null))
313 {
314 foreach (XmlScriptNode Node in this.children)
315 await Node.BuildAsync(Document, E, Variables);
316 }
317 }
318
325 public override PatternMatchResult PatternMatch(XmlNode CheckAgainst, Dictionary<string, IElement> AlreadyFound)
326 {
327 PatternMatchResult Result;
328
329 if (CheckAgainst is null)
330 {
331 if (!(this.xmlns is null))
332 {
333 Result = this.xmlns.PatternMatch(null, AlreadyFound);
334 if (Result != PatternMatchResult.Match)
335 return Result;
336 }
337
338 foreach (XmlScriptAttribute Attr in this.attributes)
339 {
340 Result = Attr.PatternMatch(null, AlreadyFound);
341 if (Result != PatternMatchResult.Match)
342 return Result;
343 }
344
345 if (!(this.children is null))
346 {
347 foreach (XmlScriptNode N2 in this.children)
348 {
349 Result = N2.PatternMatch(null, AlreadyFound);
350 if (Result != PatternMatchResult.Match)
351 return Result;
352 }
353 }
354 }
355 else
356 {
357 if (!(CheckAgainst is XmlElement E))
358 return PatternMatchResult.NoMatch;
359
360 if (E.LocalName != this.name)
361 return PatternMatchResult.NoMatch;
362
363 if (!(this.xmlns is null))
364 {
365 Result = this.xmlns.PatternMatch(CheckAgainst.NamespaceURI, AlreadyFound);
366 if (Result != PatternMatchResult.Match)
367 return Result;
368 }
369
370 foreach (XmlScriptAttribute Attr in this.attributes)
371 {
372 XmlAttribute Attr2 = E.Attributes[Attr.Name];
373
374 Result = Attr.PatternMatch(Attr2, AlreadyFound);
375 if (Result != PatternMatchResult.Match)
376 return Result;
377 }
378
379 XmlNode N = E.FirstChild;
380 bool Again;
381
382 if (!(this.children is null))
383 {
384 foreach (XmlScriptNode N2 in this.children)
385 {
386 do
387 {
388 Again = false;
389
390 if (!(N is null))
391 {
392 if (N2.IsApplicable(N))
393 {
394 if (N2.IsVector && N is XmlElement E2)
395 {
396 List<XmlElement> Elements = new List<XmlElement>() { E2 };
397
398 while (true)
399 {
400 N = N.NextSibling;
401 if (N is null)
402 break;
403 else if (N is XmlElement E3)
404 {
405 if (E3.LocalName == E2.LocalName &&
406 E3.NamespaceURI == E2.NamespaceURI)
407 {
408 Elements.Add(E3);
409 }
410 else
411 break;
412 }
413 else if ((N is XmlText && string.IsNullOrWhiteSpace(N.InnerText)) ||
414 N is XmlComment)
415 {
416 continue;
417 }
418 else
419 break;
420 }
421
422 Result = N2.PatternMatch(new ObjectVector(Elements.ToArray()), AlreadyFound);
423 }
424 else
425 {
426 Result = N2.PatternMatch(N, AlreadyFound);
427 N = N.NextSibling;
428 }
429 }
430 else if ((N2 is XmlScriptText Text && string.IsNullOrWhiteSpace(Text.Text)) ||
431 N2 is XmlScriptComment)
432 {
433 Result = PatternMatchResult.Match;
434 }
435 else if ((N is XmlText && string.IsNullOrWhiteSpace(N.InnerText)) ||
436 N is XmlComment)
437 {
438 N = N.NextSibling;
439 Again = true;
440 continue;
441 }
442 else
443 Result = N2.PatternMatch(null, AlreadyFound);
444 }
445 else
446 Result = N2.PatternMatch(null, AlreadyFound);
447
448 if (Result != PatternMatchResult.Match)
449 return Result;
450 }
451 while (Again);
452 }
453 }
454
455 while (!(N is null))
456 {
457 if (N is XmlWhitespace || N is XmlSignificantWhitespace || N is XmlComment ||
458 ((N is XmlText || N is XmlCDataSection) && string.IsNullOrWhiteSpace(N.InnerXml)))
459 {
460 N = N.NextSibling;
461 }
462 else
463 return PatternMatchResult.NoMatch;
464 }
465 }
466
467 return PatternMatchResult.Match;
468 }
469
475 public override bool IsApplicable(XmlNode CheckAgainst)
476 {
477 if (!(CheckAgainst is XmlElement E) || this.name != E.LocalName)
478 return false;
479
480 if (this.xmlns is null)
481 return true;
482
483 return this.xmlns.IsApplicable(CheckAgainst.NamespaceURI);
484 }
485 }
486}
Class managing a script expression.
Definition: Expression.cs:39
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
ScriptNode Parent
Parent node.
Definition: ScriptNode.cs:126
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
virtual bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: ScriptNode.cs:142
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed.
Definition: ScriptNode.cs:132
Contains information about a variable.
Definition: Variable.cs:10
Collection of variables.
Definition: Variables.cs:25
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:52
Abstract base class for XML Script attribute nodes.
override bool IsApplicable(XmlNode CheckAgainst)
If the node is applicable in pattern matching against CheckAgainst .
abstract PatternMatchResult PatternMatch(string CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
XmlScriptElement(string Name, XmlScriptAttribute Xmlns, XmlScriptAttribute[] Attributes, int Start, int Length, Expression Expression)
XML Script element node.
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
override bool IsApplicable(XmlNode CheckAgainst)
If the node is applicable in pattern matching against CheckAgainst .
override PatternMatchResult PatternMatch(XmlNode CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
void Add(XmlScriptNode Node)
Adds a XML Script node to the element.
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
Base class for all XML Script nodes in a parsed script tree.
abstract bool IsApplicable(XmlNode CheckAgainst)
If the node is applicable in pattern matching against CheckAgainst .
abstract PatternMatchResult PatternMatch(XmlNode CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
virtual bool IsVector
If the node represents a vector of nodes.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
PatternMatchResult
Status result of a pattern matching operation.
Definition: ScriptNode.cs:17
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38