diff options
Diffstat (limited to 'core/src/Model/Workflow.hpp')
-rw-r--r-- | core/src/Model/Workflow.hpp | 175 |
1 files changed, 132 insertions, 43 deletions
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 <cstddef> #include <cstdint> @@ -10,92 +11,180 @@ class WorkflowConnection { public: + static constexpr auto kInvalidId = std::numeric_limits<size_t>::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<size_t>::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<InputNode> mInputs; - std::vector<OutputNode> mOutputs; + std::vector<InputPin> mInputs; + std::vector<OutputPin> 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<WorkflowConnection> mConnections; - std::vector<std::unique_ptr<WorkflowStep>> mSteps; + std::vector<std::unique_ptr<WorkflowNode>> mNodes; + std::vector<std::unique_ptr<BaseValue>> 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<WorkflowNode> step); + void RemoveStep(size_t id); + + void Connect(WorkflowNode& source, int sourceNode, WorkflowNode& destination, int destinationNode); + void DisconnectBySource(WorkflowNode& source, int sourceNode); + void DisconnectByDestination(WorkflowNode& destination, int destinationNode); - 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); +private: + std::pair<WorkflowConnection&, size_t> AllocWorkflowConnection(); + std::pair<std::unique_ptr<WorkflowNode>&, 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<RuntimeNode> mNodes; + std::vector<RuntimeConnection> mConnections; + std::vector<WorkflowEvaluationError> mErrors; + std::vector<WorkflowEvaluationError> 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<BaseValue> value); + void SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> 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(); }; |