task.hpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #ifndef __TASK_HPP__
  2. #define __TASK_HPP__
  3. #include <QQueue>
  4. #include <QString>
  5. #include <QVector>
  6. #include <memory>
  7. #include <variant>
  8. #include <vector>
  9. #include <map>
  10. namespace Scheduler {
  11. enum TaskType { INSTAGRAM = 1, GENERIC = 2, OTHER = 3 };
  12. namespace TaskCode {
  13. static constexpr uint32_t GENTASKCODE = 0xFC;
  14. static constexpr uint32_t IGTASKCODE = 0xFF;
  15. }
  16. namespace TaskIndex {
  17. static constexpr uint32_t ERROR = 0x03;
  18. static constexpr uint32_t UUID = 0x00;
  19. static constexpr uint32_t ID = 0x01;
  20. static constexpr uint32_t MASK = 0x02;
  21. static constexpr uint32_t ENVFILE = 0x03;
  22. static constexpr uint32_t FILENUM = 0x04;
  23. } // namespace TaskInfo
  24. inline static std::map<std::string, uint32_t> TaskCodes{
  25. {"Generic", TaskCode::GENTASKCODE},
  26. {"Instagram", TaskCode::IGTASKCODE}
  27. };
  28. inline static uint32_t findTaskCode(QString key) {
  29. auto it = TaskCodes.find(key.toUtf8().constData());
  30. return it == TaskCodes.end() ?
  31. TaskCodes.at("Generic") :
  32. (*it).second;
  33. }
  34. /**
  35. * Files
  36. */
  37. enum FileType { VIDEO = 1, IMAGE = 2 };
  38. /**
  39. * KFileData
  40. *
  41. * Structure for holding file bytes and metadata
  42. */
  43. struct KFileData {
  44. QString name;
  45. FileType type;
  46. QString path;
  47. QByteArray bytes;
  48. // friend std::ostream &operator<<(std::ostream &out, const KFileData& file) {
  49. // out << "Name: " << file.name.toUtf8()
  50. // << "\nType: " << file.type;
  51. // return out;
  52. // }
  53. };
  54. /**
  55. * Type namespace
  56. *
  57. * Describes the types of task arguments available for use
  58. */
  59. namespace Type {
  60. static constexpr const char* TEXT = "Text";
  61. static constexpr const char* FILE = "File";
  62. static constexpr const char* STRINGVECTOR = "StringVector";
  63. static constexpr const char* FILEVECTOR = "FileVector";
  64. static constexpr const char* DATETIME = "DateTime";
  65. static constexpr const char* BOOLEAN = "Boolean";
  66. static constexpr const char* INTEGER = "Integer";
  67. } // namespace Type
  68. namespace VariantIndex {
  69. static const uint8_t BOOLEAN = 0;
  70. static const uint8_t INTEGER = 1;
  71. static const uint8_t STRVEC = 2;
  72. static const uint8_t QSTRING = 3;
  73. static const uint8_t FILEVEC = 4;
  74. } // namespace VariantIndex
  75. inline bool isIndex(uint8_t v, uint8_t i) { return v == i; }
  76. /**
  77. * Forward Declarations
  78. */
  79. class TaskArgumentBase;
  80. class Task;
  81. /**
  82. * Aliases
  83. */
  84. using TaskQueue = QQueue<Task*>;
  85. using ArgumentType = const char*;
  86. using ArgumentValues = QVector<QString>;
  87. using TypeVariant = std::variant<
  88. bool, int, QVector<QString>, QString, QVector<KFileData>
  89. >;
  90. using TaskIterator = std::vector<TaskArgumentBase*>::iterator;
  91. /**
  92. * The interface expected on our Task Arguments
  93. */
  94. class TaskArgumentBase {
  95. public:
  96. virtual const QString text() = 0;
  97. virtual const QString getStringValue() = 0;
  98. virtual uint8_t getTypeIndex() = 0;
  99. virtual TypeVariant getValue() = 0;
  100. virtual void insert(QString value) = 0;
  101. virtual void insert(KFileData file) = 0;
  102. virtual void remove(TypeVariant value) = 0;
  103. virtual void setValue(TypeVariant v) = 0;
  104. virtual bool isContainer() = 0;
  105. virtual void clear() = 0;
  106. };
  107. /**
  108. * TaskArgument
  109. *
  110. * A templated class providing a generic way for handling arguments whose types can be one from the set defined
  111. * by our TypeVariant alias
  112. */
  113. class TaskArgument : TaskArgumentBase {
  114. public:
  115. TaskArgument(QString n, ArgumentType t, TypeVariant _value) {
  116. name = n;
  117. type = t;
  118. value = _value;
  119. }
  120. /**
  121. * Move Constructor
  122. *
  123. * @constructor
  124. * @param [in] {TaskArgument&&} a The R-value reference to a TaskArgument
  125. */
  126. TaskArgument(TaskArgument&& a) :
  127. name(std::move(a.name)), type(std::move(a.type)), value(std::move(a.value)) {}
  128. /**
  129. * Copy Constructor
  130. *
  131. * @constructor
  132. * @param [in] {TaskArgument&&} a The const reference to a TaskArgument
  133. */
  134. TaskArgument(const TaskArgument& a) :
  135. name(std::move(a.name)), type(std::move(a.type)), value(std::move(a.value)) {}
  136. /**
  137. * text
  138. * @returns {QString} The name of the argument
  139. */
  140. virtual const QString text() override { return name; }
  141. /**
  142. * setValue
  143. * @param [in] {TypeVariant} new_value The new value for this argument
  144. */
  145. virtual void setValue(TypeVariant new_value) override {
  146. value = new_value;
  147. }
  148. /**
  149. * @brief getStringValue
  150. * @return [out] {QString}
  151. */
  152. virtual const QString getStringValue() override {
  153. if (isIndex(value.index(), VariantIndex::QSTRING)) {
  154. return std::get<VariantIndex::QSTRING>(value);
  155. } else if (isIndex(value.index(), VariantIndex::BOOLEAN)) {
  156. return QString::number(std::get<VariantIndex::BOOLEAN>(value));
  157. } else if (isIndex(value.index(), VariantIndex::INTEGER)) {
  158. return QString::number(std::get<VariantIndex::INTEGER>(value));
  159. }
  160. return ""; // Throw?
  161. }
  162. /**
  163. * @brief getValue
  164. * @return [out] {TypeVariant}
  165. */
  166. virtual TypeVariant getValue() override {
  167. if (isIndex(value.index(), VariantIndex::QSTRING)) {
  168. return std::get<VariantIndex::QSTRING>(value);
  169. } else if (isIndex(value.index(), VariantIndex::BOOLEAN)) {
  170. return std::get<VariantIndex::BOOLEAN>(value);
  171. } else if (isIndex(value.index(), VariantIndex::INTEGER)) {
  172. return std::get<VariantIndex::INTEGER>(value);
  173. } else if (isIndex(value.index(), VariantIndex::STRVEC)) {
  174. return std::get<VariantIndex::STRVEC>(value);
  175. } else if (isIndex(value.index(), VariantIndex::FILEVEC)) {
  176. return std::get<VariantIndex::FILEVEC>(value);
  177. }
  178. return ""; // Throw?
  179. }
  180. /**
  181. * @brief clear
  182. */
  183. virtual void clear() override {
  184. if (isIndex(value.index(), VariantIndex::STRVEC)) {
  185. std::get<VariantIndex::STRVEC>(value).clear();
  186. } else if (isIndex(value.index(), VariantIndex::FILEVEC)) {
  187. std::get<VariantIndex::FILEVEC>(value).clear();
  188. } else if (isIndex(value.index(), VariantIndex::QSTRING)) {
  189. std::get<VariantIndex::QSTRING>(value).clear();
  190. } else if (isIndex(value.index(), VariantIndex::INTEGER)) {
  191. std::get<VariantIndex::INTEGER>(value) = 0;
  192. } else if (isIndex(value.index(), VariantIndex::BOOLEAN)) {
  193. std::get<VariantIndex::BOOLEAN>(value) = false;
  194. }
  195. }
  196. /**
  197. * @brief isContainer
  198. * @return [out] {bool}
  199. */
  200. virtual bool isContainer() override {
  201. return (isIndex(value.index(), VariantIndex::STRVEC) || isIndex(value.index(), VariantIndex::FILEVEC));
  202. }
  203. /**
  204. * @brief insert
  205. * @param value
  206. */
  207. virtual void insert(QString string) override {
  208. if (isIndex(value.index(), VariantIndex::STRVEC)) {
  209. std::get<VariantIndex::STRVEC>(value).push_back(string);
  210. } else {
  211. // Unable to push. Throw?
  212. }
  213. }
  214. /**
  215. * @brief insert
  216. * @param file
  217. */
  218. virtual void insert(KFileData file) override {
  219. if (value.index() == VariantIndex::FILEVEC) {
  220. std::get<VariantIndex::FILEVEC>(value).push_back(file);
  221. } else {
  222. // Unable to push. Throw?
  223. }
  224. }
  225. /**
  226. * @brief remove
  227. * @param value
  228. */
  229. virtual void remove(TypeVariant unwanted_value) override {
  230. if (value.index() == VariantIndex::STRVEC && unwanted_value.index() == VariantIndex::QSTRING) {
  231. auto&& container = std::get<VariantIndex::STRVEC>(value);
  232. auto value_to_remove = std::get<VariantIndex::QSTRING>(unwanted_value);
  233. auto it = std::find_if(container.begin(), container.end(), [&value_to_remove](QString s) {
  234. return (s == value_to_remove);
  235. });
  236. if (it != container.end()) {
  237. container.erase(it);
  238. return;
  239. } else {
  240. throw std::out_of_range("Could not find value requested for removal");
  241. }
  242. } else if (value.index() == VariantIndex::FILEVEC && unwanted_value.index() == VariantIndex::QSTRING) {
  243. auto&& container = std::get<VariantIndex::FILEVEC>(value);
  244. auto file_to_remove = std::get<VariantIndex::QSTRING>(unwanted_value);
  245. auto it = std::find_if(container.begin(), container.end(), [&file_to_remove](Scheduler::KFileData f) {
  246. return (f.name == file_to_remove);
  247. });
  248. if (it != container.end()) {
  249. container.erase(it);
  250. return;
  251. } else {
  252. throw std::out_of_range("Could not find value requested for removal");
  253. }
  254. }
  255. throw std::invalid_argument("The value provided does not match any existing container");
  256. }
  257. /**
  258. * @brief getTypeIndex
  259. * @return
  260. */
  261. virtual uint8_t getTypeIndex() override {
  262. return value.index();
  263. }
  264. private:
  265. QString name;
  266. ArgumentType type;
  267. TypeVariant value;
  268. };
  269. using TaskArguments = std::vector<TaskArgument*>;
  270. /**
  271. * The interface expected to be implemented in all Task types
  272. */
  273. class Task {
  274. public:
  275. Task(){};
  276. Task(KFileData);
  277. Task(QVector<KFileData>);
  278. virtual void setArgument(QString name, TypeVariant arg) = 0;
  279. virtual void addArgument(QString name, Scheduler::KFileData file) = 0;
  280. virtual void addArgument(QString name, QString string) = 0;
  281. virtual void removeArgument(QString name, TypeVariant arg) = 0;
  282. virtual const TaskArguments&& getTaskArguments() = 0;
  283. virtual TaskArgument&& getTaskArgument(QString name) = 0;
  284. virtual const TypeVariant getTaskArgumentValue(QString name) = 0;
  285. virtual ArgumentValues getArgumentValues() = 0;
  286. virtual QVector<QString> getArgumentNames() = 0;
  287. virtual TaskType getType() = 0;
  288. virtual uint32_t getTaskCode() = 0;
  289. virtual void defineTaskArguments() = 0;
  290. virtual void setDefaultValues() = 0;
  291. virtual const QVector<KFileData> getFiles() = 0;
  292. virtual bool hasFiles() = 0;
  293. virtual bool isReady() = 0;
  294. virtual bool isEmpty() {
  295. bool empty = true;
  296. for (const auto& arg : getArgumentValues()) {
  297. if (!arg.isEmpty()) {
  298. empty = false;
  299. }
  300. }
  301. return empty;
  302. }
  303. virtual void clear() = 0;
  304. virtual ~Task(){};
  305. };
  306. } // namespace Scheduler
  307. #endif // __TASK_HPP__