Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
SourceReference.cs
1using System;
3using System.Reflection;
4using System.Threading.Tasks;
5using System.Xml;
6using Waher.Events;
16
18{
23 {
24 private ScriptNode source;
25 private ScriptNode alias;
26
35 : this(Source, null, Start, Length, Expression)
36 {
37 }
38
48 : base(Start, Length, Expression)
49 {
50 this.source = Source;
51 this.source?.SetParent(this);
52
53 this.alias = Alias;
54 this.alias?.SetParent(this);
55 }
56
62 public override async Task<IDataSource> GetSource(Variables Variables)
63 {
64 string Alias;
65
66 if (this.alias is null)
67 Alias = string.Empty;
68 else if (this.alias is VariableReference Ref)
69 Alias = Ref.VariableName;
70 else
71 Alias = ToString(await this.alias.EvaluateAsync(Variables));
72
73 if (this.source is VariableReference Ref2)
74 return GetDataSource(Ref2, Alias, Variables);
75 else
76 {
77 if (this.source is IEvaluateAsync AsyncSource)
78 return GetDataSource(string.Empty, Alias, await AsyncSource.EvaluateAsync(Variables), this.source);
79 else
80 return GetDataSource(string.Empty, Alias, await this.source.EvaluateAsync(Variables), this.source);
81 }
82 }
83
84 private static IDataSource GetDataSource(string Name, string Alias, IElement E, ScriptNode Source)
85 {
86 object Obj = E.AssociatedObjectValue;
87
88 if (Obj is IToMatrix ToMatrix)
89 {
90 E = ToMatrix.ToMatrix();
92 }
93
94 if (Obj is IDataSource DataSource)
95 return DataSource;
96 else if (Obj is Type T)
97 {
98 if (!typeof(IDataSource).IsAssignableFrom(T))
99 return new TypeSource(T, Alias);
100
101 ConstructorInfo CI = Types.GetDefaultConstructor(T)
102 ?? throw new ScriptRuntimeException("Type lacks default constructor: " + T.FullName, Source);
103
104 return (IDataSource)CI.Invoke(Types.NoParameters);
105 }
106 else if (Obj is string s)
107 {
108 INamedDataSource NamedDataSource = GetNamedDataSource(s);
109
110 if (NamedDataSource is null)
111 return new CollectionSource(s, Alias);
112 else
113 return NamedDataSource;
114 }
115 else if (E is ObjectMatrix OM && OM.HasColumnNames)
116 return new VectorSource(Name, Alias, VectorSource.ToGenericObjectVector(OM), Source);
117 else if (E is IVector V)
118 return new VectorSource(Name, Alias, V, Source);
119 else if (Obj is XmlDocument Doc)
120 return new XmlSource(Name, Alias, Doc, Source);
121 else if (Obj is XmlNode N)
122 return new XmlSource(Name, Alias, N, Source);
123
124 throw new ScriptRuntimeException("Data source type not supported: " + E.AssociatedObjectValue?.GetType()?.FullName, Source);
125 }
126
127 private static INamedDataSource GetNamedDataSource(string Name)
128 {
129 INamedDataSource Result;
130
131 lock (namedDataSources)
132 {
133 if (namedDataSources.TryGetValue(Name, out Result))
134 return Result;
135 }
136
137 Result = Types.FindBest<INamedDataSource, string>(Name);
138
139 lock (namedDataSources)
140 {
141 namedDataSources[Name] = Result;
142 }
143
144 return Result;
145 }
146
147 private static readonly Dictionary<string, INamedDataSource> namedDataSources = new Dictionary<string, INamedDataSource>();
148
149 private static IDataSource GetDataSource(VariableReference Source, string Alias, Variables Variables)
150 {
151 string Name = Source.VariableName;
152
153 if (Variables.TryGetVariable(Name, out Variable v))
154 return GetDataSource(Name, Alias, v.ValueElement, Source);
155
156 if (Expression.TryGetConstant(Name, Variables, out IElement ValueElement))
157 return GetDataSource(Name, Alias, ValueElement, Source);
158
159 if (Types.TryGetQualifiedNames(Name, out string[] QualifiedNames))
160 {
161 if (QualifiedNames.Length == 1)
162 {
163 Type T = Types.GetType(QualifiedNames[0]);
164
165 if (!(T is null))
166 return new TypeSource(T, Alias);
167 }
168 else
169 {
170 ChunkedList<KeyValuePair<string, object>> TypesWithCollectionNames = null;
171 Type TypeWithCollection = null;
172 bool CollectionUnique = true;
173
174 foreach (string QualifiedName in QualifiedNames)
175 {
176 Type T = Types.GetType(QualifiedName);
177 if (T is null)
178 continue;
179
180 TypeInfo TI = T.GetTypeInfo();
181 int Nr = 1;
182
183 if (!(TI.GetCustomAttribute<CollectionNameAttribute>() is null))
184 {
185 if (TypeWithCollection is null)
186 TypeWithCollection = T;
187 else
188 {
189 CollectionUnique = false;
190
191 if (TypesWithCollectionNames is null)
192 {
193 TypesWithCollectionNames = new ChunkedList<KeyValuePair<string, object>>
194 {
195 new KeyValuePair<string, object>("Type " + Nr.ToString(), TypeWithCollection.FullName)
196 };
197
198 Nr++;
199 }
200
201 TypesWithCollectionNames.Add(new KeyValuePair<string, object>(Nr.ToString(), T.FullName));
202 Nr++;
203 }
204 }
205 }
206
207 if (TypeWithCollection is null)
208 {
209 Log.Warning("A collection was referenced using a relative type name. The type does not have a collection name defined. To avoid confusion, reference the collection name as a string constant instead of a variable reference.",
210 Name, string.Empty, "DBOpt");
211 }
212 else
213 {
214 if (CollectionUnique)
215 {
216 Log.Warning("A collection was referenced using a relative type name. Multiple types are available with the same relative type name, but only one had a collection name defined for it. Using this type. Use fully.qualified type names to avoid confusion.",
217 Name, TypeWithCollection.FullName, "DBOpt");
218
219 return new TypeSource(TypeWithCollection, Alias);
220 }
221 else
222 {
223 Log.Error("A collection was referenced using a relative type name. Multiple types are available with the same relative type name and with collection names. Use fully.qualified type names to avoid confusion.",
224 Name, string.Empty, "DBOpt", TypesWithCollectionNames.ToArray());
225 }
226 }
227 }
228 }
229
230 INamedDataSource NamedDataSource = GetNamedDataSource(Name);
231
232 if (NamedDataSource is null)
233 return new CollectionSource(Name, Alias);
234 else
235 return NamedDataSource;
236 }
237
245 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
246 {
247 if (Order == SearchMethod.DepthFirst)
248 {
249 if (!(this.source?.ForAllChildNodes(Callback, State, Order) ?? true) ||
250 !(this.alias?.ForAllChildNodes(Callback, State, Order) ?? true))
251 {
252 return false;
253 }
254 }
255
256 ScriptNode NewNode;
257 bool b;
258
259 if (!(this.source is null))
260 {
261 b = !Callback(this.source, out NewNode, State);
262 if (!(NewNode is null))
263 {
264 this.source = NewNode;
265 this.source.SetParent(this);
266 }
267
268 if (b || (Order == SearchMethod.TreeOrder && !this.source.ForAllChildNodes(Callback, State, Order)))
269 return false;
270 }
271
272 if (!(this.alias is null))
273 {
274 b = !Callback(this.alias, out NewNode, State);
275 if (!(NewNode is null))
276 {
277 this.alias = NewNode;
278 this.alias.SetParent(this);
279 }
280
281 if (b || (Order == SearchMethod.TreeOrder && !this.alias.ForAllChildNodes(Callback, State, Order)))
282 return false;
283 }
284
285 if (Order == SearchMethod.BreadthFirst)
286 {
287 if (!(this.source?.ForAllChildNodes(Callback, State, Order) ?? true) ||
288 !(this.alias?.ForAllChildNodes(Callback, State, Order) ?? true))
289 {
290 return false;
291 }
292 }
293
294 return true;
295 }
296
298 public override bool Equals(object obj)
299 {
300 return (obj is SourceReference O &&
301 AreEqual(this.source, O.source) &&
302 AreEqual(this.alias, O.alias) &&
303 base.Equals(obj));
304 }
305
307 public override int GetHashCode()
308 {
309 int Result = base.GetHashCode();
310 Result ^= Result << 5 ^ GetHashCode(this.source);
311 Result ^= Result << 5 ^ GetHashCode(this.alias);
312
313 return Result;
314 }
315
316 }
317}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
Definition: Log.cs:576
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
Definition: Log.cs:692
This attribute defines the name of the collection that will house objects of this type.
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
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.
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
static Type GetType(string FullName)
Gets a type, given its full name.
Definition: Types.cs:42
static object[] NoParameters
Contains an empty array of parameter values.
Definition: Types.cs:572
static bool TryGetQualifiedNames(string UnqualifiedName, out string[] QualifiedNames)
Gets an array (possibly null) of qualified names relating to an unqualified name.
Definition: Types.cs:244
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
Definition: Types.cs:1742
Class managing a script expression.
Definition: Expression.cs:41
static bool TryGetConstant(string Name, Variables Variables, out IElement ValueElement)
Tries to get a constant value, given its name.
Definition: Expression.cs:3382
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
override string ToString()
Definition: ScriptNode.cs:359
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
Definition: ScriptNode.cs:275
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
Definition: ScriptNode.cs:132
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Definition: ScriptNode.cs:158
Represents a variable reference.
bool HasColumnNames
If the matrix has column names defined.
ToMatrix(ScriptNode Operand, bool NullCheck, int Start, int Length, Expression Expression)
To-Matrix operator.
Definition: ToMatrix.cs:22
Abstract base class for source definitions
override async Task< IDataSource > GetSource(Variables Variables)
Gets the actual data source, from its definition.
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
SourceReference(ScriptNode Source, int Start, int Length, Expression Expression)
Direct reference to a data source.
SourceReference(ScriptNode Source, ScriptNode Alias, int Start, int Length, Expression Expression)
Direct reference to a data source.
Data Source defined by a collection name
Data Source defined by a type definition
Definition: TypeSource.cs:22
static ObjectVector ToGenericObjectVector(ObjectMatrix ResultSet)
Converts an object matrix, with named columns, to a vector of objects ex nihilo.
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
Basic interface for all types of elements.
Definition: IElement.cs:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
Basic interface for vectors.
Definition: IVector.cs:9
Interface for script nodes with asynchronous evaluation
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
Interface for data sources that can be used in SQL statements.
Definition: IDataSource.cs:14
Interface for named data sources that can be used in SQL statements.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38