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