//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="BlueprintNode.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the “Software”), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and // this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED “AS IS”, // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //----------------------------------------------------------------------- //----------------------------------------------------------------------- using StgSharp.Entities; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Threading.Tasks; namespace StgSharp.BluePrint { /// /// /// /// /// Reset pipeline has risk, this operation is a direct operation to port /// in current node, the port on the other node cannot get the change. /// #pragma warning disable CA1036 public class BlueprintNode : IComparable #pragma warning restore CA1036 { private protected bool levelAvailable, nativeRequested; private protected Dictionary _inputInterfaces; private protected Dictionary _outputInterfaces; private protected int _level; private IConvertableToBlueprintNode mainOperation; private string name; internal BlueprintNode(string name, IConvertableToBlueprintNode node, bool isNative) { this.levelAvailable = false; this.name = name; nativeRequested = isNative; mainOperation = node; _inputInterfaces = new Dictionary(); _outputInterfaces = new Dictionary(); foreach (string portName in node.InputInterfacesName) { _inputInterfaces.Add(portName, null!); } foreach (string portName in node.OutputInterfacesName) { _outputInterfaces.Add(portName, null!); } } #pragma warning disable CS8618 internal BlueprintNode(string name, bool isNative, string[] inputPorts, string[] outputPorts ) #pragma warning restore CS8618 { if ((inputPorts == null) || (inputPorts.Length == 0)) { throw new ArgumentNullException(nameof(inputPorts)); } if ((outputPorts == null) || (outputPorts.Length == 0)) { throw new ArgumentNullException(nameof(outputPorts)); } levelAvailable = false; this.name = name; IsNative = isNative; _inputInterfaces = new Dictionary(); _outputInterfaces = new Dictionary(); foreach (string portName in inputPorts) { _inputInterfaces.Add(portName, null!); } foreach (string portName in outputPorts) { _outputInterfaces.Add(portName, null!); } } public bool IsNative { get => nativeRequested; internal set => nativeRequested = value; } public int Level { get { if (levelAvailable) { return _level; } _level = 0; foreach (KeyValuePair item in _inputInterfaces) { if (item.Value == null) { continue; } if (_level <= item.Value.Level) { _level = item.Value.Level; } } _level += 1; return _level; } } public string Name => name; internal Dictionary InputInterfaces => _inputInterfaces; internal Dictionary OutputInterfaces => _outputInterfaces; internal IConvertableToBlueprintNode Value { get => mainOperation; } public void AddAfter( BlueprintNode former, string formerOutputPortName, string thisInputPortName) { this.levelAvailable = false; BlueprintPipeline pipeline = new BlueprintPipeline(former, this); if (former is BeginningNode bnode) { bnode.SetCertainOutputPort(formerOutputPortName, pipeline); } else { former.SetCertainOutputPort(formerOutputPortName, pipeline); } SetCertainInputPort(thisInputPortName, pipeline); } public void AddBefore( BlueprintNode after, string thisOutputPortName, string afterInputPortName) { this.levelAvailable = false; BlueprintPipeline pipeline = new BlueprintPipeline(this, after); if (after is EndingNode enode) { enode.SetCertainInputPort(afterInputPortName, pipeline); } else { after.SetCertainInputPort(afterInputPortName, pipeline); } SetCertainOutputPort(thisOutputPortName, pipeline); } public int CompareTo(BlueprintNode other) { #pragma warning disable CA1062 return this.Level.CompareTo(other.Level); #pragma warning restore CA1062 } public virtual void Run() { try { //Console.WriteLine(name); BlueprintPipeline.WaitAll(_inputInterfaces); if (mainOperation != null) { mainOperation.ExecuteMain(in _inputInterfaces, in _outputInterfaces); } } catch (Exception) { throw; } } #region port operation public BlueprintPipeline GetCertainInputPort(string name) { BlueprintPipeline ret; if (!_inputInterfaces.TryGetValue(name, out ret)) { throw new Exception($"Cannot find the interface named {name} in node {Name}."); } return ret; } public BlueprintPipeline GetCertainOutputPort(string name) { BlueprintPipeline ret; if (!_outputInterfaces.TryGetValue(name, out ret)) { throw new Exception($"Cannot find the interface named {name} in node {Name}."); } return ret; } public void SetCertainInputPort(string name, BlueprintPipeline pipeline) { if (!_inputInterfaces.ContainsKey(name)) { throw new Exception($"Cannot find the interface named {name} in node {Name}."); } _inputInterfaces[name] = pipeline; } public void SetCertainOutputPort(string name, BlueprintPipeline pipeline) { if (!_outputInterfaces.ContainsKey(name)) { throw new Exception($"Cannot find the interface named {name} in node {Name}."); } _outputInterfaces[name] = pipeline; } #endregion }//--------------------------------- end of class ----------------------------------- public class BlueprintNodeRunException : Exception { protected BlueprintNodeRunException(SerializationInfo info, StreamingContext context) : base(info, context) { } public BlueprintNodeRunException() { } public BlueprintNodeRunException(Exception ex) : base(string.Empty, ex) { } public BlueprintNodeRunException(string message) : base(message) { } public BlueprintNodeRunException(string message, Exception innerException) : base(message, innerException) { } } }