diff options
Diffstat (limited to 'core/src/Model/Workflow/Workflow.hpp')
-rw-r--r-- | core/src/Model/Workflow/Workflow.hpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp new file mode 100644 index 0000000..a7b2c31 --- /dev/null +++ b/core/src/Model/Workflow/Workflow.hpp @@ -0,0 +1,163 @@ +#pragma once + +#include "Value.hpp" +#include "cplt_fwd.hpp" + +#include <cstddef> +#include <cstdint> +#include <limits> +#include <memory> +#include <span> +#include <string> +#include <vector> + +class WorkflowConnection { +public: + static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); + + enum Direction { + ManyToOne, + OneToMany, + }; + + struct ConnectionPoint { + size_t Node; + int Pin; + + bool operator==(const ConnectionPoint&) const = default; + }; + + std::vector<ConnectionPoint> MultiConnections; + ConnectionPoint SingleConnection; + Direction ConnectionDirection; + +public: + WorkflowConnection(); + + bool IsValid() const; + std::span<ConnectionPoint> GetSourcePoints(); + std::span<const ConnectionPoint> GetSourcePoints() const; + std::span<ConnectionPoint> GetDestinationPoints(); + std::span<const ConnectionPoint> GetDestinationPoints() const; +}; + +class WorkflowNode { +public: + static constexpr auto kInvalidId = std::numeric_limits<size_t>::max(); + + 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 InputPin { + size_t Connection = WorkflowConnection::kInvalidId; + BaseValue::Kind MatchingType = BaseValue::KindInvalid; + bool ConnectionToConst = false; + bool AllowsMultipleConnections = 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; + BaseValue::Kind GetMatchingType() const; + WorkflowConnection::Direction GetSupportedDirection() const; + }; + + struct OutputPin { + size_t Connection = WorkflowConnection::kInvalidId; + BaseValue::Kind MatchingType = BaseValue::KindInvalid; + bool AllowsMultipleConnections = false; + + bool IsConnected() const; + BaseValue::Kind GetMatchingType() const; + WorkflowConnection::Direction GetSupportedDirection() const; + }; + + friend class Workflow; + friend class WorkflowEvaluationContext; + + Workflow* mWorkflow; + size_t mId; + std::vector<InputPin> mInputs; + std::vector<OutputPin> mOutputs; + Type mType; + Kind mKind; + +public: + WorkflowNode(Type type, Kind kind); + virtual ~WorkflowNode() = 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, WorkflowNode& output, int outputNodeId); + void DisconnectInput(int nodeId); + bool IsInputConnected(int nodeId) const; + + void ConnectOutput(int nodeId, WorkflowNode& input, int inputNodeId); + void DisconnectOutput(int nodeId); + bool IsOutputConnected(int nodeId) const; + + virtual void Evaluate(WorkflowEvaluationContext& ctx) = 0; + +protected: + 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<WorkflowNode>> mNodes; + std::vector<std::unique_ptr<BaseValue>> mConstants; + +public: + WorkflowConnection* GetConnectionById(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); + + bool Connect(WorkflowNode& sourceNode, int sourcePin, WorkflowNode& destinationNode, int destinationPin); + bool DisconnectBySource(WorkflowNode& sourceNode, int sourcePin); + bool DisconnectByDestination(WorkflowNode& destinationNode, int destinationPin); + +private: + std::pair<WorkflowConnection&, size_t> AllocWorkflowConnection(); + std::pair<std::unique_ptr<WorkflowNode>&, size_t> AllocWorkflowStep(); +}; |