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