File indexing completed on 2024-05-19 05:07:26
0001 /* 0002 SPDX-FileCopyrightText: 2013-2015 Christian Dávid <christian-david@web.de> 0003 SPDX-FileCopyrightText: 2019 Thomas Baumgart <tbaumgart@kde.org> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef ONLINEJOB_H 0008 #define ONLINEJOB_H 0009 0010 #define STRINGIFY(x) #x 0011 #define TOSTRING(x) STRINGIFY(x) 0012 #define BADTASKEXCEPTION badTaskCast("Casted onlineTask with wrong type. " __FILE__ ":" TOSTRING(__LINE__)) 0013 #define EMPTYTASKEXCEPTION emptyTask("Requested onlineTask of onlineJob without any task. " __FILE__ ":" TOSTRING(__LINE__)) 0014 0015 #include <stdexcept> 0016 #include <QMetaType> 0017 #include <QString> 0018 #include "mymoneyobject.h" 0019 #include "onlinejobmessage.h" 0020 0021 class onlineTask; 0022 class MyMoneyAccount; 0023 0024 namespace eMyMoney { 0025 namespace OnlineJob { 0026 enum class sendingState; 0027 } 0028 } 0029 0030 /** 0031 * @brief Class to share jobs which can be processed by an online banking plugin 0032 * 0033 * This class stores only the status information and a pointer to an @r onlineTask which stores 0034 * the real data. So onlineJob is similar to an shared pointer. 0035 * 0036 * If you know the type of the onlineTask, @r onlineJobTyped is the first choice to use. 0037 * 0038 * It is save to use because accesses to pointers (e.g. task() ) throw an exception if onlineJob is null. 0039 * 0040 * Online jobs are usually not created directly but over @r onlineJobAdministration::createOnlineJob. This is 0041 * required to allow loading of onlineTasks at runtime and only if needed. 0042 * 0043 * This class was created to help writing stable and reliable code. Before an unsafe structure (= pointer) 0044 * is accessed it is checked. Exceptions are thrown if the content is unsafe. 0045 * 0046 * @see onlineTask 0047 * @see onlineJobTyped 0048 * @todo LOW make data implicitly shared 0049 */ 0050 class onlineJobPrivate; 0051 class KMM_MYMONEY_EXPORT onlineJob : public MyMoneyObject 0052 { 0053 Q_DECLARE_PRIVATE(onlineJob) 0054 0055 KMM_MYMONEY_UNIT_TESTABLE 0056 0057 public: 0058 /** 0059 * @brief Constructor for null onlineJobs 0060 * 0061 * A onlineJob which is null cannot become valid again. 0062 * @see isNull() 0063 */ 0064 onlineJob(); 0065 explicit onlineJob(const QString &id); 0066 0067 /** 0068 * @brief Default constructor 0069 * 0070 * The onlineJob takes ownership of the task. The task is deleted in the destructor. 0071 */ 0072 onlineJob(onlineTask* task, const QString& id); // krazy:exclude=explicit 0073 onlineJob(onlineTask* task); // krazy:exclude=explicit 0074 0075 /** 0076 * @brief Create new onlineJob as copy of other 0077 * 0078 * This constructor does not copy the status information but the task only. 0079 */ 0080 onlineJob(const QString &id, 0081 const onlineJob& other); 0082 0083 onlineJob(const onlineJob & other); 0084 onlineJob(onlineJob && other); 0085 onlineJob & operator=(onlineJob other); 0086 friend void swap(onlineJob& first, onlineJob& second); 0087 0088 virtual ~onlineJob(); 0089 0090 void setTask(onlineTask *task); 0091 0092 /** 0093 * @brief Returns task attached to this onlineJob 0094 * 0095 * You should not store this pointer but use onlineJob::task() (or @r onlineJobTyped::task()) 0096 * every time you access it. 0097 * 0098 * @note The return type may change in future (e.g. to an atomic pointer). But you can always expect 0099 * the operator @c -> to work like it does for onlineTask*. 0100 * 0101 * @throws emptyTask if isNull() 0102 */ 0103 onlineTask* task(); 0104 0105 /** @copydoc task(); */ 0106 const onlineTask* task() const; 0107 0108 /** 0109 * @brief Returns task attached to this onlineJob as const 0110 * @throws emptyTask if isNull() 0111 */ 0112 const onlineTask* constTask() const; 0113 0114 /** 0115 * @brief Returns task of type T attached to this onlineJob 0116 * 0117 * Internally a dynamic_cast is done and the result is checked. 0118 * 0119 * @throws emptyTask if isNull() 0120 * @throws badTaskCast if attached task cannot be casted to T 0121 */ 0122 template<class T> T* task(); 0123 0124 /** @copydoc task() */ 0125 template<class T> const T* task() const; 0126 template<class T> const T* constTask() const { 0127 return task<T>(); 0128 } 0129 0130 template<class T> bool canTaskCast() const; 0131 0132 QString taskIid() const; 0133 0134 /** 0135 * @brief Return the purpose of the job 0136 */ 0137 QString purpose() const; 0138 0139 /** 0140 * @brief Account this job is related to 0141 * 0142 * Each job must have an account on which the job operates. This is used to determine 0143 * the correct onlinePlugin which can execute this job. If the job is related to more 0144 * than one account (e.g. a password change) select a random one. 0145 * 0146 * @return accountId or QString() if none is set or job isNull. 0147 */ 0148 virtual QString responsibleAccount() const; 0149 0150 /** 0151 * @brief Returns the MyMoneyAccount this job is related to 0152 * @see responsibleAccount() 0153 */ 0154 MyMoneyAccount responsibleMyMoneyAccount() const; 0155 0156 /** 0157 * @brief Check if this onlineJob is editable by the user 0158 * 0159 * A job is no longer editable by the user if it is used for documentary purposes 0160 * e.g. the job was sent to the bank. In that case create a new job based on the 0161 * old one. 0162 * 0163 * @todo make it possible to use onlineJobs as templates 0164 */ 0165 virtual bool isEditable() const; 0166 0167 /** 0168 * @brief Checks if this onlineJob has an attached task 0169 * 0170 * @return true if no task is attached to this job 0171 */ 0172 virtual bool isNull() const; 0173 0174 /** 0175 * @brief Checks if an valid onlineTask is attached 0176 * 0177 * @return true if task().isValid(), false if isNull() or !task.isValid() 0178 */ 0179 virtual bool isValid() const; 0180 0181 /** 0182 * @brief DateTime the job was sent to the bank 0183 * 0184 * A valid return does not mean that this job was accepted by the bank. 0185 * 0186 * @return A valid QDateTime if send to bank, an QDateTime() if not send. 0187 */ 0188 virtual QDateTime sendDate() const; 0189 0190 /** 0191 * @brief Mark this job as send 0192 * 0193 * To be used by online plugin only! 0194 * 0195 * Set dateTime to QDateTime to mark unsend. 0196 */ 0197 virtual void setJobSend(const QDateTime &dateTime); 0198 virtual void setJobSend(); 0199 0200 /** 0201 * @brief The bank's answer to this job 0202 * 0203 * To be used by online plugin only! 0204 * 0205 * Set dateTime to QDateTime() and bankAnswer to noState to mark unsend. If bankAnswer == noState dateTime.isNull() must be true! 0206 */ 0207 void setBankAnswer(const eMyMoney::OnlineJob::sendingState state, const QDateTime &dateTime); 0208 void setBankAnswer(const eMyMoney::OnlineJob::sendingState state); 0209 0210 /** 0211 * @brief DateTime of the last status update by the bank 0212 * 0213 */ 0214 QDateTime bankAnswerDate() const; 0215 0216 /** 0217 * @brief Returns last status sand by bank 0218 * @return 0219 */ 0220 eMyMoney::OnlineJob::sendingState bankAnswerState() const; 0221 0222 /** 0223 * @brief locks the onlineJob for sending it 0224 * 0225 * Used when the job is in sending process by the online plugin. 0226 * 0227 * A locked onlineJob cannot be removed from the storage. 0228 * 0229 * @note The onlineJob can still be edited and stored. But it should be done by 0230 * the one how owns the lock only. 0231 * 0232 * @todo Enforce the lock somehow? Note: the onlinePlugin must still be able to 0233 * write to the job. 0234 * 0235 * @param enable true locks the job, false unlocks the job 0236 */ 0237 virtual bool setLock(bool enable = true); 0238 0239 /** 0240 * @brief Get lock status 0241 */ 0242 virtual bool isLocked() const; 0243 0244 /** 0245 * @brief Make this onlineJob a "new" onlineJob 0246 * 0247 * Removes all status information, log, and the id. Only 0248 * the task is kept. 0249 */ 0250 virtual void reset(); 0251 0252 /** 0253 * @brief addJobMessage 0254 * 0255 * To be used by online plugin only. 0256 * @param message 0257 */ 0258 void addJobMessage(const onlineJobMessage &message); 0259 0260 /** 0261 * @brief Convenient method to set add a log message 0262 */ 0263 void addJobMessage(const eMyMoney::OnlineJob::MessageType& type, const QString& sender, const QString& message, const QString& errorCode, const QDateTime& timestamp); 0264 void addJobMessage(const eMyMoney::OnlineJob::MessageType& type, const QString& sender, const QString& message, const QString& errorCode); 0265 void addJobMessage(const eMyMoney::OnlineJob::MessageType& type, const QString& sender, const QString& message); 0266 0267 0268 /** 0269 * @brief jobMessageList 0270 * @return 0271 */ 0272 virtual QList<onlineJobMessage> jobMessageList() const; 0273 0274 0275 void clearJobMessageList(); 0276 0277 /** 0278 * @brief Thrown if a cast of a task fails 0279 * 0280 * This is inspired by std::bad_cast 0281 */ 0282 class badTaskCast : public std::runtime_error 0283 { 0284 public: 0285 explicit badTaskCast(const char *msg) : std::runtime_error(msg) {} // krazy:exclude=inline 0286 }; 0287 0288 /** 0289 * @brief Thrown if a task of an invalid onlineJob is requested 0290 */ 0291 class emptyTask : public std::runtime_error 0292 { 0293 public: 0294 explicit emptyTask(const char *msg) : std::runtime_error(msg) {} // krazy:exclude=inline 0295 }; 0296 0297 /** @brief onlineTask attached to this job */ 0298 onlineTask* m_task; 0299 0300 private: 0301 0302 /** @brief Copies stored pointers (used by copy constructors) */ 0303 inline void copyPointerFromOtherJob(const onlineJob& other); 0304 }; 0305 0306 inline void swap(onlineJob& first, onlineJob& second) // krazy:exclude=inline 0307 { 0308 using std::swap; 0309 swap(first.d_ptr, second.d_ptr); 0310 swap(first.m_task, second.m_task); 0311 } 0312 0313 inline onlineJob::onlineJob(onlineJob && other) : onlineJob() // krazy:exclude=inline 0314 { 0315 swap(*this, other); 0316 } 0317 0318 inline onlineJob & onlineJob::operator=(onlineJob other) // krazy:exclude=inline 0319 { 0320 swap(*this, other); 0321 return *this; 0322 } 0323 0324 template<class T> 0325 T* onlineJob::task() 0326 { 0327 T* ret = dynamic_cast<T*>(m_task); 0328 if (ret == 0) 0329 throw EMPTYTASKEXCEPTION; 0330 return ret; 0331 } 0332 0333 template<class T> 0334 const T* onlineJob::task() const 0335 { 0336 const T* ret = dynamic_cast<const T*>(m_task); 0337 if (ret == 0) 0338 throw BADTASKEXCEPTION; 0339 return ret; 0340 } 0341 0342 Q_DECLARE_METATYPE(onlineJob) 0343 0344 #endif // ONLINEJOB_H