Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XmlScriptElement.cs
2using System.Threading.Tasks;
3using System.Xml;
8
10{
15 {
16 private XmlScriptAttribute xmlns;
17 private readonly XmlScriptAttribute[] attributes;
18 private ChunkedList<XmlScriptNode> children = null;
19 private readonly string name;
20 private readonly int nrAttributes;
21 private bool isAsync;
22
32 public XmlScriptElement(string Name, XmlScriptAttribute Xmlns, XmlScriptAttribute[] Attributes,
34 : base(Start, Length, Expression)
35 {
36 this.name = Name;
37
38 this.xmlns = Xmlns;
39 this.xmlns?.SetParent(this);
40
41 this.attributes = Attributes;
42 this.attributes?.SetParent(this);
43
44 this.nrAttributes = Attributes.Length;
45
46 this.CalcIsAsync();
47 }
48
49 private void CalcIsAsync()
50 {
51 this.isAsync = this.xmlns?.IsAsynchronous ?? false;
52 if (this.isAsync)
53 return;
54
56 int i, c;
57
58 for (i = 0; i < this.nrAttributes; i++)
59 {
60 if (this.attributes[i]?.IsAsynchronous ?? false)
61 {
62 this.isAsync = true;
63 return;
64 }
65 }
66
67 Loop = this.children?.FirstChunk;
68
69 while (!(Loop is null))
70 {
71 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
72 {
73 if (Loop[i]?.IsAsynchronous ?? false)
74 {
75 this.isAsync = true;
76 return;
77 }
78 }
79
80 Loop = Loop.Next;
81 }
82 }
83
88 public override bool IsAsynchronous => this.isAsync;
89
94 public void Add(XmlScriptNode Node)
95 {
96 if (this.children is null)
97 this.children = new ChunkedList<XmlScriptNode>();
98
99 this.children.Add(Node);
100 Node?.SetParent(this);
101
102 this.isAsync |= Node?.IsAsynchronous ?? false;
103 }
104
112 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
113 {
115 int i, c;
116
117 if (Order == SearchMethod.DepthFirst)
118 {
119 if (!(this.xmlns?.ForAllChildNodes(Callback, State, Order) ?? true))
120 return false;
121
122 for (i = 0; i < this.nrAttributes; i++)
123 {
124 if (!this.attributes[i].ForAllChildNodes(Callback, State, Order))
125 return false;
126 }
127
128 Loop = this.children?.FirstChunk;
129
130 while (!(Loop is null))
131 {
132 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
133 {
134 if (!(Loop[i]?.ForAllChildNodes(Callback, State, Order) ?? false))
135 return false;
136 }
137
138 Loop = Loop.Next;
139 }
140 }
141
142 ScriptNode NewNode;
143 bool RecalcIsAsync = false;
144 bool b;
145
146 if (!(this.xmlns is null))
147 {
148 b = !Callback(this.xmlns, out NewNode, State);
149 if (!(NewNode is null) && NewNode is XmlScriptAttribute NewAttr)
150 {
151 this.xmlns = NewAttr;
152 this.xmlns.SetParent(this);
153
154 RecalcIsAsync = true;
155 }
156
157 if (b || (Order == SearchMethod.TreeOrder && !this.xmlns.ForAllChildNodes(Callback, State, Order)))
158 {
159 if (RecalcIsAsync)
160 this.CalcIsAsync();
161
162 return false;
163 }
164 }
165
166 for (i = 0; i < this.nrAttributes; i++)
167 {
168 b = !Callback(this.attributes[i], out NewNode, State);
169 if (!(NewNode is null) && NewNode is XmlScriptAttribute Attr)
170 {
171 this.attributes[i] = Attr;
172 Attr.SetParent(this);
173
174 RecalcIsAsync = true;
175 }
176
177 if (b || (Order == SearchMethod.TreeOrder && !this.attributes[i].ForAllChildNodes(Callback, State, Order)))
178 {
179 if (RecalcIsAsync)
180 this.CalcIsAsync();
181
182 return false;
183 }
184 }
185
186 Loop = this.children?.FirstChunk;
187 while (!(Loop is null))
188 {
189 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
190 {
191 b = !Callback(Loop[i], out NewNode, State);
192 if (!(NewNode is null) && NewNode is XmlScriptNode Node2)
193 {
194 Loop[i] = Node2;
195 Node2.SetParent(this);
196
197 RecalcIsAsync = true;
198 }
199
200 if (b || (Order == SearchMethod.TreeOrder && !Loop[i].ForAllChildNodes(Callback, State, Order)))
201 {
202 if (RecalcIsAsync)
203 this.CalcIsAsync();
204
205 return false;
206 }
207 }
208
209 Loop = Loop.Next;
210 }
211
212 if (RecalcIsAsync)
213 this.CalcIsAsync();
214
215 if (Order == SearchMethod.BreadthFirst)
216 {
217 if (!(this.xmlns?.ForAllChildNodes(Callback, State, Order) ?? true))
218 return false;
219
220 for (i = 0; i < this.nrAttributes; i++)
221 {
222 if (!this.attributes[i].ForAllChildNodes(Callback, State, Order))
223 return false;
224 }
225
226 Loop = this.children?.FirstChunk;
227
228 while (!(Loop is null))
229 {
230 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
231 {
232 if (!(Loop[i]?.ForAllChildNodes(Callback, State, Order) ?? false))
233 return false;
234 }
235
236 Loop = Loop.Next;
237 }
238 }
239
240 return true;
241 }
242
249 internal override void Build(XmlDocument Document, XmlElement Parent, Variables Variables)
250 {
251 string ns = this.xmlns?.GetValue(Variables) ?? null;
252 XmlElement E;
253
254 if (ns is null)
255 {
256 if (Parent is null || string.IsNullOrEmpty(ns = Parent.NamespaceURI))
257 {
258 if (Variables.TryGetVariable(XmlScriptValue.ParentNamespaceVariableName, out Variable v) && v.ValueObject is string s)
259 ns = s;
260 }
261
262 if (string.IsNullOrEmpty(ns))
263 E = Document.CreateElement(this.name);
264 else
265 E = Document.CreateElement(this.name, ns);
266 }
267 else
268 E = Document.CreateElement(this.name, ns);
269
270 if (Parent is null)
271 Document.AppendChild(E);
272 else
273 Parent.AppendChild(E);
274
275 foreach (XmlScriptAttribute Attr in this.attributes)
276 Attr.Build(Document, E, Variables);
277
278 if (!(this.children is null))
279 {
280 foreach (XmlScriptNode Node in this.children)
281 Node.Build(Document, E, Variables);
282 }
283 }
284
291 internal override async Task BuildAsync(XmlDocument Document, XmlElement Parent, Variables Variables)
292 {
293 if (!this.isAsync)
294 {
295 this.Build(Document, Parent, Variables);
296 return;
297 }
298
299 string ns;
300 XmlElement E;
301
302 if (this.xmlns is null)
303 ns = null;
304 else
305 ns = await this.xmlns.GetValueAsync(Variables);
306
307 if (ns is null)
308 {
309 if (Parent is null || string.IsNullOrEmpty(ns = Parent.NamespaceURI))
310 {
311 if (Variables.TryGetVariable(XmlScriptValue.ParentNamespaceVariableName, out Variable v) && v.ValueObject is string s)
312 ns = s;
313 }
314
315 if (string.IsNullOrEmpty(ns))
316 E = Document.CreateElement(this.name);
317 else
318 E = Document.CreateElement(this.name, ns);
319 }
320 else
321 E = Document.CreateElement(this.name, ns);
322
323 if (Parent is null)
324 Document.AppendChild(E);
325 else
326 Parent.AppendChild(E);
327
328 foreach (XmlScriptAttribute Attr in this.attributes)
329 await Attr.BuildAsync(Document, E, Variables);
330
331 if (!(this.children is null))
332 {
333 foreach (XmlScriptNode Node in this.children)
334 await Node.BuildAsync(Document, E, Variables);
335 }
336 }
337
344 public override PatternMatchResult PatternMatch(XmlNode CheckAgainst, Dictionary<string, IElement> AlreadyFound)
345 {
346 PatternMatchResult Result;
347
348 if (CheckAgainst is null)
349 {
350 if (!(this.xmlns is null))
351 {
352 Result = this.xmlns.PatternMatch(null, AlreadyFound);
353 if (Result != PatternMatchResult.Match)
354 return Result;
355 }
356
357 foreach (XmlScriptAttribute Attr in this.attributes)
358 {
359 Result = Attr.PatternMatch(null, AlreadyFound);
360 if (Result != PatternMatchResult.Match)
361 return Result;
362 }
363
364 if (!(this.children is null))
365 {
366 foreach (XmlScriptNode N2 in this.children)
367 {
368 Result = N2.PatternMatch(null, AlreadyFound);
369 if (Result != PatternMatchResult.Match)
370 return Result;
371 }
372 }
373 }
374 else
375 {
376 if (!(CheckAgainst is XmlElement E))
377 return PatternMatchResult.NoMatch;
378
379 if (E.LocalName != this.name)
380 return PatternMatchResult.NoMatch;
381
382 if (!(this.xmlns is null))
383 {
384 Result = this.xmlns.PatternMatch(CheckAgainst.NamespaceURI, AlreadyFound);
385 if (Result != PatternMatchResult.Match)
386 return Result;
387 }
388
389 bool Wildcard = false;
390
391 foreach (XmlScriptAttribute Attr in this.attributes)
392 {
393 if (string.IsNullOrEmpty(Attr.Name))
394 Wildcard = true;
395 else
396 {
397 XmlAttribute Attr2 = E.Attributes[Attr.Name];
398
399 Result = Attr.PatternMatch(Attr2, AlreadyFound);
400 if (Result != PatternMatchResult.Match)
401 return Result;
402 }
403 }
404
405 if (!Wildcard)
406 {
407 foreach (XmlAttribute Attr in E.Attributes)
408 {
409 if (Attr.Name == "xmlns")
410 continue;
411
412 bool Found = false;
413
414 foreach (XmlScriptAttribute Attr2 in this.attributes)
415 {
416 if (Attr2.Name == Attr.Name)
417 {
418 Found = true;
419 break;
420 }
421 }
422
423 if (!Found)
424 return PatternMatchResult.NoMatch;
425 }
426 }
427
428 XmlNode N = E.FirstChild;
429 bool Again;
430
431 if (!(this.children is null))
432 {
433 foreach (XmlScriptNode N2 in this.children)
434 {
435 if (N2.IsWhitespace)
436 continue;
437
438 do
439 {
440 Again = false;
441
442 if (!(N is null))
443 {
444 if (N2.IsApplicable(N, null))
445 {
446 if (N2.IsVector)
447 {
448 if (N is XmlElement E2)
449 {
450 ChunkedList<XmlElement> Elements = new ChunkedList<XmlElement>() { E2 };
451
452 while (true)
453 {
454 N = N.NextSibling;
455 if (N is null)
456 break;
457 else if (N is XmlElement E3)
458 {
459 if (N2.IsApplicable(N, E2))
460 Elements.Add(E3);
461 else
462 break;
463 }
464 else if ((N is XmlText && string.IsNullOrWhiteSpace(N.InnerText)) ||
465 N is XmlComment)
466 {
467 continue;
468 }
469 else
470 break;
471 }
472
473 Result = N2.PatternMatch(new ObjectVector(Elements.ToArray()), AlreadyFound);
474 }
475 else if ((N is XmlText && string.IsNullOrWhiteSpace(N.InnerText)) ||
476 N is XmlComment)
477 {
478 N = N.NextSibling;
479 Again = true;
480 continue;
481 }
482 else
483 {
484 Result = N2.PatternMatch(N, AlreadyFound);
485 N = N.NextSibling;
486 }
487 }
488 else
489 {
490 Result = N2.PatternMatch(N, AlreadyFound);
491 N = N.NextSibling;
492 }
493 }
494 else if ((N is XmlText && string.IsNullOrWhiteSpace(N.InnerText)) ||
495 N is XmlComment)
496 {
497 N = N.NextSibling;
498 Again = true;
499 continue;
500 }
501 else
502 Result = N2.PatternMatch(null, AlreadyFound);
503 }
504 else
505 Result = N2.PatternMatch(null, AlreadyFound);
506
507 if (Result != PatternMatchResult.Match)
508 return Result;
509 }
510 while (Again);
511 }
512 }
513
514 while (!(N is null))
515 {
516 if (N is XmlWhitespace || N is XmlSignificantWhitespace || N is XmlComment ||
517 ((N is XmlText || N is XmlCDataSection) && string.IsNullOrWhiteSpace(N.InnerXml)))
518 {
519 N = N.NextSibling;
520 }
521 else
522 return PatternMatchResult.NoMatch;
523 }
524 }
525
526 return PatternMatchResult.Match;
527 }
528
535 public override bool IsApplicable(XmlNode CheckAgainst, XmlElement First)
536 {
537 if (!(CheckAgainst is XmlElement E))
538 return false;
539
540 if (First is null)
541 {
542 if (this.name != E.LocalName)
543 return false;
544
545 if (this.xmlns is null)
546 return true;
547
548 return this.xmlns.IsApplicable(CheckAgainst.NamespaceURI);
549 }
550 else
551 {
552 return
553 E.LocalName == First.LocalName &&
554 E.NamespaceURI == First.NamespaceURI;
555 }
556 }
557 }
558}
Node referencing a chunk in a ChunkedList<T>
Definition: ChunkNode.cs:11
ChunkNode< T > Next
Next chunk
Definition: ChunkNode.cs:26
int Pos
Index after the last element in chunk.
Definition: ChunkNode.cs:51
int Start
Index of first element in chunk.
Definition: ChunkNode.cs:46
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
ChunkNode< T > FirstChunk
First chunk
Definition: ChunkedList.cs:259
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
T[] ToArray()
Returns an array containing all elements of the collection.
Class managing a script expression.
Definition: Expression.cs:41
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 or created.
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:56
Abstract base class for XML Script attribute nodes.
abstract PatternMatchResult PatternMatch(string CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
override bool IsApplicable(XmlNode CheckAgainst, XmlElement First)
If the node is applicable in pattern matching against CheckAgainst .
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 PatternMatchResult PatternMatch(XmlNode CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
override bool IsApplicable(XmlNode CheckAgainst, XmlElement First)
If the node is applicable in pattern matching against CheckAgainst .
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.
virtual bool IsWhitespace
If the node represents whitespace.
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.
abstract bool IsApplicable(XmlNode CheckAgainst, XmlElement First)
If the node is applicable in pattern matching against CheckAgainst .
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