aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Workflow/Workflow.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/Model/Workflow/Workflow.hpp')
-rw-r--r--core/src/Model/Workflow/Workflow.hpp163
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();
+};