From 4e5730e1fcef150ce2f13f52a278890589ca96ad Mon Sep 17 00:00:00 2001 From: rtk0c Date: Fri, 16 Apr 2021 16:49:28 -0700 Subject: More work on workflows - WorkflowStep -> WorkflowNode - Added initial kinds of WorkflowNode's --- core/src/Model/Workflow.hpp | 175 +++++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 43 deletions(-) (limited to 'core/src/Model/Workflow.hpp') diff --git a/core/src/Model/Workflow.hpp b/core/src/Model/Workflow.hpp index a90ef21..2c83816 100644 --- a/core/src/Model/Workflow.hpp +++ b/core/src/Model/Workflow.hpp @@ -1,6 +1,7 @@ #pragma once -#include "EvaluatedValue.hpp" +#include "Model/EvaluatedValue.hpp" +#include "cplt_fwd.hpp" #include #include @@ -10,92 +11,180 @@ class WorkflowConnection { public: + static constexpr auto kInvalidId = std::numeric_limits::max(); + size_t Source; size_t Destination; + int SourcePin; + int DestinationPin; + +public: + WorkflowConnection(); + + bool IsValid() const; }; -class WorkflowStep { +class WorkflowNode { public: static constexpr auto kInvalidId = std::numeric_limits::max(); - // TODO do we even need this? - // enum Type { - // NumericAdditionType, - // NumericSubtractionType, - // NumericMultiplicationType, - // NumericDivisionType, - // NumericExpressionType, - // TextFormattingType, - // FormInputType, - // DatabaseRowsInputType, - // DocumentTemplateExpansionType, - // - // InvalidType, - // TypeCount = InvalidType, - // }; + enum Type { + InputType, + TransformType, + OutputType, + }; + + enum Kind { + KD_NumericAddition, + KD_NumericSubtraction, + KD_NumericMultiplication, + KD_NumericDivision, + KD_NumericExpression, + KD_TextFormatting, + KD_DocumentTemplateExpansion, + KD_FormInput, + KD_DatabaseRowsInput, + + InvalidKind, + KindCount = InvalidKind, + }; protected: - struct InputNode { - size_t ConnectedStep = kInvalidId; - int ConnectedNodeIndex = -1; - BaseValue::Type MatchingType = BaseValue::InvalidType; + struct InputPin { + size_t Connection = WorkflowConnection::kInvalidId; + BaseValue::Kind MatchingType = BaseValue::KindInvalid; + bool ConnectionToConst = false; + /// A constant connection connects from a user-specified constant value, feeding to a valid \c Destination and \c DestinationPin (i.e. input pins). + bool IsConstantConnection() const; bool IsConnected() const; }; - struct OutputNode { - size_t ConnectedStep = kInvalidId; - int ConnectedNodeIndex = -1; - BaseValue::Type MatchingType = BaseValue::InvalidType; + struct OutputPin { + size_t Connection = WorkflowConnection::kInvalidId; + BaseValue::Kind MatchingType = BaseValue::KindInvalid; bool IsConnected() const; }; friend class Workflow; + friend class WorkflowEvaluationError; + friend class WorkflowEvaluationContext; + Workflow* mWorkflow; size_t mId; - std::vector mInputs; - std::vector mOutputs; + std::vector mInputs; + std::vector mOutputs; + Type mType; + Kind mKind; public: - virtual ~WorkflowStep() = default; + WorkflowNode(Type type, Kind kind); + virtual ~WorkflowNode() = default; - WorkflowStep(const WorkflowStep&) = delete; - WorkflowStep& operator=(const WorkflowStep&) = delete; - WorkflowStep(WorkflowStep&&) = default; - WorkflowStep& operator=(WorkflowStep&&) = default; + WorkflowNode(const WorkflowNode&) = delete; + WorkflowNode& operator=(const WorkflowNode&) = delete; + WorkflowNode(WorkflowNode&&) = default; + WorkflowNode& operator=(WorkflowNode&&) = default; size_t GetId() const; + Type GetType() const; + Kind GetKind() const; - void ConnectInput(int nodeId, size_t outputId, int outputNodeId); + void ConnectInput(int nodeId, WorkflowNode& output, int outputNodeId); void DisconnectInput(int nodeId); bool IsInputConnected(int nodeId) const; - void ConnectOutput(int nodeId, size_t inputId, int inputNodeId); + void ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId); void DisconnectOutput(int nodeId); bool IsOutputConnected(int nodeId) const; + virtual void Evaluate(WorkflowEvaluationContext& ctx) = 0; + protected: - /// Child classes should call this whenever \c mInputs and \c mOutputs are about to be modified (append or remove) - /// after invocation of the constructor. - void OnIOAboutToChange(); - void OnIOChanged(); + InputPin& InsertInputPin(int atIdx); + void RemoveInputPin(int pin); + void SwapInputPin(int a, int b); + OutputPin& InsertOutputPin(int atIdx); + void RemoveOutputPin(int pin); + void SwapOutputPin(int a, int b); + + /* For \c Workflow to invoke, override by implementations */ + + void OnAttach(Workflow& workflow, size_t newId) {} + void OnDetach() {} }; class Workflow { private: + friend class WorkflowEvaluationContext; + std::vector mConnections; - std::vector> mSteps; + std::vector> mNodes; + std::vector> mConstants; public: WorkflowConnection* GetConnectionById(size_t id); - WorkflowStep* GetStepById(size_t id); + WorkflowNode* GetStepById(size_t id); + BaseValue* GetConstantById(size_t id); + + void AddStep(std::unique_ptr step); + void RemoveStep(size_t id); - void Connect(size_t source, int sourceNode, size_t destination, int destinationNode); - void DisconnectBySource(size_t source, int sourceNode); - void DisconnectByDestination(size_t destination, int destinationNode); + void Connect(WorkflowNode& source, int sourceNode, WorkflowNode& destination, int destinationNode); + void DisconnectBySource(WorkflowNode& source, int sourceNode); + void DisconnectByDestination(WorkflowNode& destination, int destinationNode); + +private: + std::pair AllocWorkflowConnection(); + std::pair&, size_t> AllocWorkflowStep(); +}; + +class WorkflowEvaluationError { +public: + enum MessageType : int16_t { + Error, + Warning, + }; + + enum PinType : int16_t { + NoPin, + InputPin, + OutputPin, + }; + +public: + std::string Message; + size_t NodeId; + int PinId; + PinType PinType; + MessageType Type; }; class WorkflowEvaluationContext { +private: + struct RuntimeNode; + struct RuntimeConnection; + + Workflow* mWorkflow; + std::vector mNodes; + std::vector mConnections; + std::vector mErrors; + std::vector mWarnings; + +public: + WorkflowEvaluationContext(Workflow& workflow); + + BaseValue* GetConnectionValue(size_t id, bool constant); + BaseValue* GetConnectionValue(const WorkflowNode::InputPin& inputPin); + void SetConnectionValue(size_t id, std::unique_ptr value); + void SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr value); + + void ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin); + void ReportError(std::string message, const WorkflowNode& node); + void ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin); + void ReportWarning(std::string message, const WorkflowNode& node); + /// Run until all possible paths have been evaluated. + void Run(); }; -- cgit v1.2.3-70-g09d2