aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Workflow.hpp
blob: a90ef21a7049174d85c5b862ef225f0d1d16eeb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#pragma once

#include "EvaluatedValue.hpp"

#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <vector>

class WorkflowConnection {
public:
	size_t Source;
	size_t Destination;
};

class WorkflowStep {
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,
	//	};

protected:
	struct InputNode {
		size_t ConnectedStep = kInvalidId;
		int ConnectedNodeIndex = -1;
		BaseValue::Type MatchingType = BaseValue::InvalidType;

		bool IsConnected() const;
	};

	struct OutputNode {
		size_t ConnectedStep = kInvalidId;
		int ConnectedNodeIndex = -1;
		BaseValue::Type MatchingType = BaseValue::InvalidType;

		bool IsConnected() const;
	};

	friend class Workflow;
	Workflow* mWorkflow;
	size_t mId;
	std::vector<InputNode> mInputs;
	std::vector<OutputNode> mOutputs;

public:
	virtual ~WorkflowStep() = default;

	WorkflowStep(const WorkflowStep&) = delete;
	WorkflowStep& operator=(const WorkflowStep&) = delete;
	WorkflowStep(WorkflowStep&&) = default;
	WorkflowStep& operator=(WorkflowStep&&) = default;

	size_t GetId() const;

	void ConnectInput(int nodeId, size_t outputId, int outputNodeId);
	void DisconnectInput(int nodeId);
	bool IsInputConnected(int nodeId) const;

	void ConnectOutput(int nodeId, size_t inputId, int inputNodeId);
	void DisconnectOutput(int nodeId);
	bool IsOutputConnected(int nodeId) const;

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();
};

class Workflow {
private:
	std::vector<WorkflowConnection> mConnections;
	std::vector<std::unique_ptr<WorkflowStep>> mSteps;

public:
	WorkflowConnection* GetConnectionById(size_t id);
	WorkflowStep* GetStepById(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);
};

class WorkflowEvaluationContext {

};