4using System.Threading.Tasks;
23 [CollectionName(
"Processors")]
27 [Index(
"ParentId",
"NodeId")]
30 private Guid objectId = Guid.Empty;
31 private Guid parentId = Guid.Empty;
33 private string nodeId =
string.Empty;
34 private string oldId =
null;
36 private List<ProcessorNode> children =
null;
37 private int siblingOrdinal = 0;
38 private bool childrenLoaded =
false;
39 private readonly
object synchObject =
new object();
40 private DateTime created = DateTime.Now;
41 private DateTime updated = DateTime.MinValue;
59 return Node.thingReference;
67 public override bool Equals(
object obj)
72 return this.nodeId == Ref.NodeId && this.SourceId == Ref.SourceId && this.Partition == Ref.Partition;
81 return this.nodeId.GetHashCode() ^
93 set => this.objectId = value;
101 get => this.parentId;
102 set => this.parentId = value;
111 set => this.created = value;
117 [DefaultValueDateTimeMinValue]
121 set => this.updated = value;
130 get => this.siblingOrdinal;
131 set => this.siblingOrdinal = value;
137 [Header(14,
"ID:", 0)]
138 [Page(15,
"Processor", 0)]
139 [ToolTip(16,
"Processor identity in the collection of processors.")]
147 this.thingReference =
null;
149 if (this.oldId is
null && !
string.IsNullOrEmpty(value))
157 protected string OldId => this.oldId;
174 StringBuilder sb =
new StringBuilder();
177 sb.Append(this.nodeId);
190 return sb.ToString();
268 if (this.objectId == Guid.Empty)
279 Message.Updated = DateTime.Now;
301 if (this.state <
NodeState.ErrorUnsigned)
305 await this.RaiseUpdate();
310 if (this.state <
NodeState.WarningUnsigned)
314 await this.RaiseUpdate();
323 await this.RaiseUpdate();
343 await this.NodeStateChanged();
346 internal async Task NodeStateChanged()
355 Timestamp = DateTime.UtcNow
426 if (this.objectId == Guid.Empty)
429 bool Removed =
false;
452 bool ErrorsFound =
false;
453 bool WarningsFound =
false;
454 bool InformationFound =
false;
465 WarningsFound =
true;
469 InformationFound =
true;
480 NewStateUnsigned =
NodeState.ErrorUnsigned;
482 else if (WarningsFound)
484 NewStateSigned =
NodeState.WarningSigned;
485 NewStateUnsigned =
NodeState.WarningUnsigned;
487 else if (InformationFound)
490 NewStateUnsigned =
NodeState.Information;
502 if (this.state != NewStateSigned)
504 this.state = NewStateSigned;
506 await this.RaiseUpdate();
511 if (this.state != NewStateUnsigned)
513 this.state = NewStateUnsigned;
515 await this.RaiseUpdate();
520 await this.NodeStateChanged();
531 internal Task RaiseUpdate()
533 return this.OnUpdate.Raise(
this, EventArgs.Empty);
544 string Suffix =
string.Empty;
557 Suffix =
" (" + i.ToString() +
")";
590 if (!this.childrenLoaded)
591 this.LoadChildren().Wait();
593 return !(this.children is
null) && this.children.Count > 0;
624 [Obsolete(
"Use the asynchronous GetParent() method instead.")]
634 if (!(this.parent is
null))
637 if (this.parentId == Guid.Empty)
640 this.parent = await this.LoadParent();
641 if (this.parent is
null)
642 throw new Exception(
"Parent not found.");
656 while (!(Loop is
null))
658 if (Loop is T Ancestor)
677 if (this.updated == DateTime.MinValue)
691 set => this.state = value;
702 return this.GetChildNodes();
706 private async Task<IEnumerable<INode>> GetChildNodes()
708 if (!this.childrenLoaded)
709 await this.LoadChildren();
711 lock (this.synchObject)
713 if (this.children is
null)
714 return Array.Empty<
INode>();
716 return this.children.ToArray();
720 private async Task LoadChildren()
722 List<ProcessorNode> Children =
new List<ProcessorNode>();
731 lock (this.synchObject)
733 this.children =
null;
735 if (Children.Count > 0)
741 this.children = Children;
744 this.childrenLoaded =
true;
747 if (!(ToUpdate is
null))
758 if (this.ChildrenOrdered)
760 Children.Sort((n1, n2) => n1.siblingOrdinal.CompareTo(n2.siblingOrdinal));
765 Children.Sort((n1, n2) => n1.nodeId.CompareTo(n2.nodeId));
777 if (this.ChildrenOrdered)
788 Child.siblingOrdinal = Expected;
793 return ToUpdate?.ToArray();
799 internal async Task<ProcessorNode> LoadParent()
801 if (!(this.parent is
null))
804 if (this.parentId == Guid.Empty)
864 LinkedList<Parameter> Result =
new LinkedList<Parameter>();
868 if (!(this.parent is
null))
871 if (!this.childrenLoaded)
872 await this.LoadChildren();
874 if (!(this.children is
null))
878 lock (this.synchObject)
880 i = this.children.Count;
886 string s = this.state
switch
896 if (!
string.IsNullOrEmpty(s))
901 if (this.updated != DateTime.MinValue)
928 LinkedList<Message> Result =
new LinkedList<Message>();
942 List<Message> Result =
new List<Message>();
947 return Result.ToArray();
984 if (!this.ChildrenOrdered)
987 if (!this.childrenLoaded)
988 await this.LoadChildren();
990 if (this.children is
null)
1000 int i = this.children.IndexOf(Child);
1004 Child2 = this.children[i - 1];
1006 this.children.RemoveAt(i);
1007 this.children.Insert(i - 1, Child);
1009 i = Child.siblingOrdinal;
1010 Child.siblingOrdinal = Child2.siblingOrdinal;
1011 Child2.siblingOrdinal = i;
1021 Timestamp = DateTime.UtcNow
1035 if (!this.ChildrenOrdered)
1038 if (!this.childrenLoaded)
1039 await this.LoadChildren();
1041 if (this.children is
null)
1049 lock (this.children)
1051 int c = this.children.Count;
1052 int i = this.children.IndexOf(Child);
1053 if (i < 0 || i + 1 >= c)
1056 Child2 = this.children[i + 1];
1058 this.children.RemoveAt(i);
1059 this.children.Insert(i + 1, Child);
1061 i = Child.siblingOrdinal;
1062 Child.siblingOrdinal = Child2.siblingOrdinal;
1063 Child2.siblingOrdinal = i;
1073 Timestamp = DateTime.UtcNow
1100 throw new Exception(
"Child must be a processor node.");
1102 if (this.objectId == Guid.Empty)
1103 throw new Exception(
"Parent node must be persisted before you can add nodes to it.");
1105 if (!this.childrenLoaded)
1106 await this.LoadChildren();
1108 Node.parentId = this.objectId;
1114 lock (this.synchObject)
1116 if (this.children is
null)
1117 this.children =
new List<ProcessorNode>();
1118 else if ((c = this.children.Count) > 0)
1119 After = this.children[c - 1];
1123 Node.siblingOrdinal = this.children.Count;
1126 this.children.Add(Node);
1129 if (!(ToUpdate is
null))
1132 if (Node.objectId == Guid.Empty)
1141 NodeType = Node.GetType().FullName,
1143 DisplayName = await Node.GetTypeNameAsync(
Language),
1158 Timestamp = DateTime.UtcNow
1161 if (this.ChildrenOrdered && !(After is
null))
1163 Event.AfterNodeId = After.nodeId;
1170 await Node.NodeUpdated();
1172 await this.RaiseUpdate();
1180 this.updated = DateTime.Now;
1192 ParentPartition = this.Partition,
1201 Timestamp = DateTime.UtcNow
1204 if (this.oldId != this.nodeId)
1207 this.oldId = this.nodeId;
1216 if (this.objectId != Guid.Empty)
1219 await this.RaiseUpdate();
1230 throw new Exception(
"Child must be a processor node.");
1232 if (!this.childrenLoaded)
1233 await this.LoadChildren();
1238 lock (this.synchObject)
1240 if (!(this.children is
null))
1242 i = this.children.IndexOf(Node);
1245 this.children.RemoveAt(i);
1246 if (i == 0 && this.children.Count == 0)
1247 this.children =
null;
1256 if (!(ToUpdate is
null))
1259 Node.parentId = Guid.Empty;
1262 if (Node.objectId != Guid.Empty)
1265 await this.RaiseUpdate();
1272 Timestamp = DateTime.UtcNow
1286 if (this.parent.childrenLoaded)
1290 lock (this.parent.synchObject)
1292 if (!(this.parent.children is
null))
1294 if (this.parent.children.Remove(
this))
1296 if (this.parent.children.Count == 0)
1297 this.parent.children =
null;
1304 if (!(ToUpdate is
null))
1309 if (!this.childrenLoaded)
1310 await this.LoadChildren();
1312 if (!(this.children is
null))
1314 List<ProcessorNode> Children = this.children;
1315 this.children =
null;
1319 Child.parent =
null;
1320 Child.parentId = Guid.Empty;
1325 this.children =
null;
1328 if (this.objectId != Guid.Empty)
1331 this.objectId = Guid.Empty;
1345 return Task.FromResult<IEnumerable<ICommand>>(
new ICommand[]
Class representing an event.
Static class managing the application event log. Applications and services log events on this static ...
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.
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.
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static async Task< object > LoadObject(string CollectionName, object ObjectId)
Loads an object given its Object ID ObjectId and its collection name CollectionName .
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
Clears all messages for a processor.
Logs a message on a processor.
Defines a message logged on a processor node.
MessageType Type
Message Type
DateTime Created
When node was created.
string EventId
Optional Event ID.
Base class for all processor nodes.
async Task< Parameter[]> GetDisplayableParameterAraryAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
virtual Task LogMessageAsync(MessageType Type, string Body)
Logs a message on the node.
string SourceId
Optional ID of source containing node.
virtual Task< bool > RemoveWarningAsync(string EventId)
Removes warning messages with a given event ID from the node.
virtual Task< bool > CanDestroyAsync(RequestOrigin Caller)
If the node can be destroyed to by the caller.
virtual Task< bool > CanAddAsync(RequestOrigin Caller)
If the node can be added to by the caller.
virtual async Task LogMessageAsync(MessageType Type, string EventId, string Body)
Logs a message on the node.
async Task< Message[]> GetMessageArrayAsync(RequestOrigin Caller)
Gets messages logged on the node.
virtual Task LogInformationAsync(string Body)
Logs an informational message on the node.
virtual Task< bool > CanViewAsync(RequestOrigin Caller)
If the node is visible to the caller.
NodeState State
Current overall state of the node.
DateTime Created
When node was created.
virtual Task LogErrorAsync(string EventId, string Body)
Logs an error message on the node.
DateTime LastChanged
When the node was last updated.
virtual ProcessorNode[] SortChildrenAfterLoadLocked(List< ProcessorNode > Children)
Method that allows the node to sort its children, after they have been loaded.
virtual async Task< bool > MoveUpAsync(ProcessorNode Child, RequestOrigin Caller)
Tries to move the child node up.
virtual bool HasCommands
If the node has registered commands or not.
virtual Task LogWarningAsync(string Body)
Logs an warning message on the node.
virtual async Task DestroyAsync()
Destroys the node. If it is a child to a parent node, it is removed from the parent first.
virtual bool IsReadable
If the node can be read.
virtual async Task NodeUpdated()
Persists changes to the node, and generates a node updated event.
static async Task< string > GetUniqueNodeId(string ProcessorId)
Gets a Processor ID, based on ProcessorId that is not already available in the database.
INode Parent
Parent Node, or null if a root node.
virtual Task LogWarningAsync(string EventId, string Body)
Logs an warning message on the node.
virtual Task< bool > RemoveWarningAsync()
Removes warning messages with an empty event ID from the node.
virtual async Task< bool > MoveDownAsync(RequestOrigin Caller)
Tries to move the node down.
int SiblingOrdinal
Sibling ordinal, used to order siblings when ordered.
async Task< INode > GetParent()
Gets the parent of the node.
Task< IEnumerable< INode > > ChildNodes
Child nodes. If no child nodes are available, null is returned.
async Task< T > GetAncestor< T >()
Tries to get an ancestor node of a given type, if one exists.
virtual Task LogErrorAsync(string Body)
Logs an error message on the node.
virtual Task< bool > RemoveErrorAsync(string EventId)
Removes error messages with a given event ID from the node.
override int GetHashCode()
Serves as the default hash function.
virtual bool ChildrenOrdered
If the children of the node have an intrinsic order (true), or if the order is not important (false).
ProcessorNode()
Base class for all processor nodes.
virtual async Task AddAsync(INode Child)
Adds a new child to the node.
abstract Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
override bool Equals(object obj)
Determines whether the specified object is equal to the current object.
virtual Task< bool > RemoveErrorAsync()
Removes error messages with an empty event ID from the node.
virtual string LocalId
If provided, an ID for the node, but unique locally between siblings. Can be null,...
virtual async Task< IEnumerable< Parameter > > GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
virtual bool IsControllable
If the node can be controlled.
Guid ObjectId
Object ID in persistence layer.
virtual Task< bool > RemoveMessageAsync(MessageType Type)
Removes messages with empty event IDs from the node.
virtual string LogId
If provided, an ID for the node, as it would appear or be used in system logs. Can be null,...
bool HasChildren
If the source has any child sources.
virtual Task< bool > RemoveInformationAsync()
Removes warning messages with an empty event ID from the node.
virtual async Task< bool > RemoveAsync(INode Child)
Removes a child from the node.
virtual Task< bool > RemoveInformationAsync(string EventId)
Removes an informational message on the node.
override string ToString()
virtual async Task< IEnumerable< Message > > GetMessagesAsync(RequestOrigin Caller)
Gets messages logged on the node.
Guid ParentId
Object ID of parent node in persistence layer.
virtual Task< IEnumerable< ICommand > > Commands
Available command objects. If no commands are available, null is returned.
abstract Task< bool > AcceptsChildAsync(INode Child)
If the node accepts a presumptive child, i.e. can receive as a child (if that child accepts the node ...
virtual Task< bool > CanEditAsync(RequestOrigin Caller)
If the node can be edited by the caller.
virtual async Task< bool > MoveDownAsync(ProcessorNode Child, RequestOrigin Caller)
Tries to move the child node down.
virtual async Task< bool > MoveUpAsync(RequestOrigin Caller)
Tries to move the node up.
virtual async Task< bool > RemoveMessageAsync(MessageType Type, string EventId)
Logs a message on the node.
abstract Task< bool > AcceptsParentAsync(INode Parent)
If the node accepts a presumptive parent, i.e. can be added to that parent (if that parent accepts th...
DateTime Updated
When node was last updated. If it has not been updated, value will be DateTime.MinValue.
string Partition
Optional partition in which the Node ID is unique.
string OldId
Previous ID of node (during update).
EventHandlerAsync OnUpdate
Event raised when node has been updated.
virtual ProcessorNode[] CheckOrderLocked(List< ProcessorNode > Children)
Checks the ordering of children.
virtual Task LogInformationAsync(string EventId, string Body)
Logs an informational message on the node.
virtual async Task UpdateAsync()
Updates the node (in persisted storage).
Defines the Processors data source. This data source contains a tree structure of processor of nodes
const string SourceID
Source ID for the processors data source.
A chunked list is a linked list of chunks of objects of type T .
void AddRange(IEnumerable< T > Collection)
Adds a range of elements (last) to the list.
T[] ToArray()
Returns an array containing all elements of the collection.
Contains information about a language.
async Task< Namespace > GetNamespaceAsync(string Name)
Gets the namespace object, given its name, if available.
async Task< Namespace > CreateNamespaceAsync(string Name)
Creates a new language namespace, or updates an existing language namespace, if one exist with the sa...
Contains information about a namespace in a language.
Task< LanguageString > GetStringAsync(int Id)
Gets the string object, given its ID, if available.
Basic access point for runtime language localization.
static async Task< Language > GetDefaultLanguageAsync()
Gets the default language.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
DateTime-valued parameter.
Contains information about a message logged on a node.
Base class for all node parameters.
string Name
Parameter Name.
virtual object StringValue
String representation of parameter value
Tokens available in request.
static readonly RequestOrigin Empty
Empty request origin.
bool HasPrivilege(string Privilege)
If the origin has a given privilege.
static string EmptyIfSame(string Id1, string Id2)
Returns Id1 if different, string.Empty if the same.
Node status changed event.
Contains a reference to a thing
Base Interface for all processor nodes.
Interface for actuator nodes.
Interface for nodes that are published through the concentrator interface.
Task< bool > MoveUpAsync(RequestOrigin Caller)
Tries to move the node up.
INode Parent
Parent Node, or null if a root node.
Task< bool > MoveDownAsync(RequestOrigin Caller)
Tries to move the node down.
Interface for sensor nodes.
Interface for thing references.
delegate Task EventHandlerAsync(object Sender, EventArgs e)
Asynchronous version of EventArgs.
TypeNameSerialization
How the type name should be serialized.
MessageType
Type of message.
NodeState
State of a node.