Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
GroupProcessor.cs
1using System.Threading.Tasks;
8
10{
14 public class GroupProcessor : IProcessor<object>
15 {
16 private readonly ScriptNode[] groupBy;
17 private readonly ScriptNode[] groupNames;
18 private readonly bool[] groupByAsynchronous;
19 private readonly IIterativeEvaluator[] iterators;
20 private readonly bool[] iteratorUsesElement;
21 private readonly bool[] iteratorAsynchronous;
22 private readonly Variables variables;
23 private readonly int iteratorCount;
24 private readonly int count;
25 private readonly bool isAsynchronous;
26 private IProcessor<object> processor;
27 private ObjectProperties objectVariables = null;
28 private object[] last = null;
29 private object[] current = null;
30
40 ScriptNode[] GroupBy, ScriptNode[] GroupNames, ScriptNode[] Columns,
41 ref ScriptNode Having)
42 {
43 this.variables = Variables;
44 this.groupBy = GroupBy;
45 this.groupNames = GroupNames;
46 this.isAsynchronous = false;
47
48 int i, c = GroupBy.Length;
49 bool b;
50
51 this.groupByAsynchronous = new bool[c];
52 this.count = c;
53
54 for (i = 0; i < c; i++)
55 {
56 b = this.groupByAsynchronous[i] = GroupBy[i].IsAsynchronous;
57 this.isAsynchronous |= b;
58 }
59
60 if (!this.isAsynchronous && !(GroupNames is null))
61 {
62 for (i = 0, c = GroupNames.Length; i < c; i++)
63 {
64 if (GroupNames[i].IsAsynchronous)
65 {
66 this.isAsynchronous = true;
67 break;
68 }
69 }
70 }
71
72 if (!this.isAsynchronous && !(Columns is null))
73 {
74 for (i = 0, c = Columns.Length; i < c; i++)
75 {
76 if (Columns[i].IsAsynchronous)
77 {
78 this.isAsynchronous = true;
79 break;
80 }
81 }
82 }
83
84 if (!this.isAsynchronous && !(Having is null))
85 this.isAsynchronous |= Having.IsAsynchronous;
86
88
89 if (!(Columns is null))
90 {
91 for (i = 0, c = Columns.Length; i < c; i++)
92 FindIterators(ref Columns[i], Iterators);
93 }
94
95 FindIterators(ref Having, Iterators);
96
97 this.iterators = Iterators.ToArray();
98 this.iteratorCount = this.iterators.Length;
99
100 this.iteratorUsesElement = new bool[this.iteratorCount];
101 this.iteratorAsynchronous = new bool[this.iteratorCount];
102
103 for (i = 0; i < this.iteratorCount; i++)
104 {
105 this.iteratorUsesElement[i] = this.iterators[i].UsesElement;
106 this.iteratorAsynchronous[i] = b = this.iterators[i].IsAsynchronous;
107 this.isAsynchronous |= b;
108 }
109 }
110
116 {
117 this.processor = Processor;
118 }
119
120 internal static void FindIterators(ref ScriptNode Node, ChunkedList<IIterativeEvaluator> Iterators)
121 {
122 if (Node is IIterativeEvaluation IterativeEvaluation2)
123 {
124 int IteratorIndex = Iterators.Count;
125 IIterativeEvaluator Evaluator = IterativeEvaluation2.CreateEvaluator();
126 Iterators.Add(Evaluator);
127
128 ScriptNode Node0 = Node;
129
130 Node = new GroupIteratorValue(Evaluator, IteratorIndex,
131 Node.Start, Node.Length, Node.Expression);
132
133 Node.SetParent(Node0.Parent);
134 }
135 else if (Node is GroupIteratorValue GroupIteratorValue2)
136 Iterators.Add(GroupIteratorValue2.Iterator);
137 else
138 Node?.ForAllChildNodes(FindIterators, Iterators, SearchMethod.TreeOrder);
139 }
140
141 internal static bool FindIterators(ScriptNode Node, out ScriptNode NewNode, object State)
142 {
143 NewNode = null;
144
145 if (Node is IIterativeEvaluation IterativeEvaluation)
146 {
148 int IteratorIndex = Iterators.Count;
149 IIterativeEvaluator Evaluator = IterativeEvaluation.CreateEvaluator();
150 Iterators.Add(Evaluator);
151
152 NewNode = new GroupIteratorValue(Evaluator, IteratorIndex,
153 Node.Start, Node.Length, Node.Expression);
154 }
155 else if (Node is GroupIteratorValue GroupIteratorValue)
156 {
159 }
160
161 return true;
162 }
163
167 public bool IsAsynchronous => this.isAsynchronous;
168
174 public bool Process(object Object)
175 {
176 IIterativeEvaluator Iterator;
177 IElement E;
178 object o1, o2;
179 int i, j;
180
181 if (this.objectVariables is null)
182 this.objectVariables = new ObjectProperties(Object, this.variables);
183 else
184 this.objectVariables.Object = Object;
185
186 if (this.last is null)
187 {
188 this.last = new object[this.count];
189
190 for (i = 0; i < this.count; i++)
191 {
192 E = this.groupBy[i].Evaluate(this.objectVariables);
193 this.last[i] = E.AssociatedObjectValue;
194 }
195
196 if (this.iteratorCount > 0)
197 {
198 for (j = 0; j < this.iteratorCount; j++)
199 this.iterators[j].RestartEvaluator();
200 }
201 }
202 else
203 {
204 if (this.current is null)
205 this.current = new object[this.count];
206
207 bool Same = true;
208
209 for (i = 0; i < this.count; i++)
210 {
211 E = this.groupBy[i].Evaluate(this.objectVariables);
212
213 o1 = this.last[i];
214 o2 = this.current[i] = E.AssociatedObjectValue;
215
216 if ((o1 is null ^ o2 is null) ||
217 (!(o1 is null) && !o1.Equals(o2)))
218 {
219 Same = false;
220 }
221 }
222
223 if (!Same)
224 {
225 if (this.processor is null)
226 return false;
227
228 GroupObject Obj = this.GetGroupObject();
229 this.last = null;
230
231 if (!this.processor.Process(Obj))
232 return false;
233
234 this.last = this.current;
235 this.current = null;
236 }
237 }
238
239 if (this.iteratorCount > 0)
240 {
241 for (j = 0; j < this.iteratorCount; j++)
242 {
243 Iterator = this.iterators[j];
244
245 if (this.iteratorUsesElement[j])
246 {
247 E = Iterator.Evaluate(this.objectVariables);
248 Iterator.AggregateElement(E);
249 }
250 else
252 }
253 }
254
255 return true;
256 }
257
258 private GroupObject GetGroupObject()
259 {
260 IElement[] Aggregates = new IElement[this.iteratorCount];
261 IIterativeEvaluator Iterator;
262 int i;
263
264 for (i = 0; i < this.iteratorCount; i++)
265 {
266 Iterator = this.iterators[i];
267 Aggregates[i] = Iterator.GetAggregatedResult();
268 Iterator.RestartEvaluator();
269 }
270
271 return new GroupObject(this.last, Aggregates, this.groupNames, this.variables);
272 }
273
279 public async Task<bool> ProcessAsync(object Object)
280 {
281 IIterativeEvaluator Iterator;
282 IElement E;
283 object o1, o2;
284 int i, j;
285
286 if (this.objectVariables is null)
287 this.objectVariables = new ObjectProperties(Object, this.variables);
288 else
289 this.objectVariables.Object = Object;
290
291 if (this.last is null)
292 {
293 this.last = new object[this.count];
294
295 for (i = 0; i < this.count; i++)
296 {
297 if (this.groupByAsynchronous[i])
298 E = await this.groupBy[i].EvaluateAsync(this.objectVariables);
299 else
300 E = this.groupBy[i].Evaluate(this.objectVariables);
301
302 this.last[i] = E.AssociatedObjectValue;
303 }
304
305 if (this.iteratorCount > 0)
306 {
307 for (j = 0; j < this.iteratorCount; j++)
308 this.iterators[j].RestartEvaluator();
309 }
310 }
311 else
312 {
313 if (this.current is null)
314 this.current = new object[this.count];
315
316 bool Same = true;
317
318 for (i = 0; i < this.count; i++)
319 {
320 if (this.groupByAsynchronous[i])
321 E = await this.groupBy[i].EvaluateAsync(this.objectVariables);
322 else
323 E = this.groupBy[i].Evaluate(this.objectVariables);
324
325 o1 = this.last[i];
326 o2 = this.current[i] = E.AssociatedObjectValue;
327
328 if ((o1 is null ^ o2 is null) ||
329 (!(o1 is null) && !o1.Equals(o2)))
330 {
331 Same = false;
332 }
333 }
334
335 if (!Same)
336 {
337 if (this.processor is null)
338 return false;
339
340 GroupObject Obj = this.GetGroupObject();
341 this.last = null;
342
343 if (!await this.processor.ProcessAsync(Obj))
344 return false;
345
346 this.last = this.current;
347 this.current = null;
348 }
349 }
350
351 if (this.iteratorCount > 0)
352 {
353 for (j = 0; j < this.iteratorCount; j++)
354 {
355 Iterator = this.iterators[j];
356
357 if (this.iteratorUsesElement[j])
358 {
359 if (this.iteratorAsynchronous[j])
360 E = await Iterator.EvaluateAsync(this.objectVariables);
361 else
362 E = Iterator.Evaluate(this.objectVariables);
363
364 Iterator.AggregateElement(E);
365 }
366 else
368 }
369 }
370
371 return true;
372 }
373
378 public bool Flush()
379 {
380 if (!(this.last is null))
381 {
382 GroupObject Obj = this.GetGroupObject();
383 this.last = null;
384
385 if (!this.processor.Process(Obj))
386 return false;
387 }
388
389 return this.processor.Flush();
390 }
391
396 public async Task<bool> FlushAsync()
397 {
398 if (!(this.last is null))
399 {
400 GroupObject Obj = this.GetGroupObject();
401 this.last = null;
402
403 if (!await this.processor.ProcessAsync(Obj))
404 return false;
405 }
406
407 return await this.processor.FlushAsync();
408 }
409 }
410}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
int Count
Number of elements in collection.
Definition: ChunkedList.cs:68
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.
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
Expression Expression
Expression of which the node is a part.
Definition: ScriptNode.cs:177
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
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:88
Returns the result value from an iterator.
Represents a collection of objects grouped together useing a GROUP BY construct.
Definition: GroupObject.cs:12
Processor that groups items into groups, and processes aggregated elements.
bool Process(object Object)
Processes an object synchronously.
bool Flush()
Called at the end of processing, to allow for flushing of buffers, etc.
async Task< bool > FlushAsync()
Called at the end of processing, to allow for flushing of buffers, etc.
bool IsAsynchronous
If the processor operates asynchronously.
async Task< bool > ProcessAsync(object Object)
Processes an object asynchronously.
GroupProcessor(Variables Variables, ScriptNode[] GroupBy, ScriptNode[] GroupNames, ScriptNode[] Columns, ref ScriptNode Having)
Processor that groups items into groups, and processes aggregated elements.
void SetInnerProcessor(IProcessor< object > Processor)
Sets the inner processor.
Collection of variables.
Definition: Variables.cs:25
Interface for processors of objects.
Definition: IProcessor.cs:9
bool Process(T Object)
Processes an object synchronously.
bool Flush()
Called at the end of processing, to allow for flushing of buffers, etc.
Task< bool > FlushAsync()
Called at the end of processing, to allow for flushing of buffers, etc.
Task< bool > ProcessAsync(T Object)
Processes an object asynchronously.
Basic interface for all types of elements.
Definition: IElement.cs:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
A function that can be iteratively evaluated, meaning it can be iteratively computed one element at a...
An interative evaluator of a function supporting the IIterativeEvaluation interface.
IElement GetAggregatedResult()
Gets the aggregated result.
Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the evaluator, using the variables provided in the Variables collection and an object inst...
IElement Evaluate(Variables Variables)
Evaluates the evaluator, using the variables provided in the Variables collection and an object inst...
void AggregateElement(IElement Element)
Aggregates one new element.
void RestartEvaluator()
Restarts the evaluator.
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38