Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

mymoneymap.h

Go to the documentation of this file.
00001 #include <stdint.h>
00002 #include <qmap.h>
00003 #include <qptrstack.h>
00004 #include <kmymoney/mymoneyexception.h>
00005 
00006 #ifndef MYMONEYMAP_H
00007 #define MYMONEYMAP_H
00008 
00009 #define MY_OWN_DEBUG 0
00010 
00027 template <class Key, class T>
00028 class MyMoneyMap : protected QMap<Key, T>
00029 {
00030 public:
00031   // typedef QMapConstIterator<Key, T> const_iterator;
00032 
00033   MyMoneyMap() : QMap<Key, T>() {}
00034   virtual ~MyMoneyMap() {}
00035 
00036   void startTransaction(unsigned long* id = 0)
00037   {
00038     m_stack.push(new MyMoneyMapStart(this, id));
00039   }
00040 
00041   void rollbackTransaction(void)
00042   {
00043     if(m_stack.count() == 0)
00044       throw new MYMONEYEXCEPTION("No transaction started to rollback changes");
00045 
00046     // undo all actions
00047     MyMoneyMapAction* action;
00048     while(m_stack.count()) {
00049       action = m_stack.pop();
00050       action->undo();
00051       delete action;
00052     }
00053   }
00054 
00055   bool commitTransaction(void)
00056   {
00057     if(m_stack.count() == 0)
00058       throw new MYMONEYEXCEPTION("No transaction started to commit changes");
00059 
00060     bool rc = m_stack.count() > 1;
00061     m_stack.setAutoDelete(true);
00062     m_stack.clear();
00063     return rc;
00064   }
00065 
00066   void insert(const Key& key, const T& obj)
00067   {
00068     if(m_stack.count() == 0)
00069       throw new MYMONEYEXCEPTION("No transaction started to insert new element into container");
00070 
00071     // store object in
00072     m_stack.push(new MyMoneyMapInsert(this, key, obj));
00073   }
00074 
00075   void modify(const Key& key, const T& obj)
00076   {
00077     if(m_stack.count() == 0)
00078       throw new MYMONEYEXCEPTION("No transaction started to modify element in container");
00079 
00080 #if 0
00081     // had to take this out, because we use QPair in one instance as key
00082     if(key.isEmpty())
00083       throw new MYMONEYEXCEPTION("No key to update object");
00084 #endif
00085 
00086     m_stack.push(new MyMoneyMapModify(this, key, obj));
00087   }
00088 
00089   void remove(const Key& key)
00090   {
00091     if(m_stack.count() == 0)
00092       throw new MYMONEYEXCEPTION("No transaction started to remove element from container");
00093 
00094 #if 0
00095     // had to take this out, because we use QPair in one instance as key
00096     if(key.isEmpty())
00097       throw new MYMONEYEXCEPTION("No key to remove object");
00098 #endif
00099 
00100     m_stack.push(new MyMoneyMapRemove(this, key));
00101   }
00102 
00103   MyMoneyMap<Key, T>& operator= (const QMap<Key, T>& m)
00104   {
00105     if(m_stack.count() != 0) {
00106       throw new MYMONEYEXCEPTION("Cannot assign whole container during transaction");
00107     }
00108     QMap<Key, T>::operator=(m);
00109     return *this;
00110   }
00111 
00112 
00113   inline QValueList<T> values(void) const
00114   {
00115     return QMap<Key,T>::values();
00116   }
00117 
00118   inline QValueList<Key> keys(void) const
00119   {
00120     return QMap<Key,T>::keys();
00121   }
00122 
00123   const T& operator[] ( const Key& k ) const
00124         { QT_CHECK_INVALID_MAP_ELEMENT; return QMap<Key,T>::operator[](k); }
00125 
00126   inline Q_TYPENAME QMap<Key, T>::const_iterator find(const Key& k) const
00127   {
00128     return QMap<Key,T>::find(k);
00129   }
00130 
00131   inline Q_TYPENAME QMap<Key, T>::const_iterator begin(void) const
00132   {
00133     return QMap<Key,T>::begin();
00134   }
00135 
00136   inline Q_TYPENAME QMap<Key, T>::const_iterator end(void) const
00137   {
00138     return QMap<Key,T>::end();
00139   }
00140 
00141   inline bool contains(const Key& k) const
00142   {
00143     return find(k) != end();
00144   }
00145 
00146   inline void map(QMap<Key, T>& that) const
00147   {
00148     //QMap<Key, T>* ptr = dynamic_cast<QMap<Key, T>* >(this);
00149     //that = *ptr;
00150     that = *(dynamic_cast<QMap<Key, T>* >(const_cast<MyMoneyMap<Key, T>* >(this)));
00151   }
00152 
00153   inline size_t count(void) const
00154   {
00155     return QMap<Key, T>::count();
00156   }
00157 
00158 #if MY_OWN_DEBUG
00159   void dump(void) const
00160   {
00161     printf("Container dump\n");
00162     printf(" items in container = %d\n", count());
00163     printf(" items on stack     = %d\n", m_stack.count());
00164 
00165     const_iterator it;
00166     for(it = begin(); it != end(); ++it) {
00167       printf("  %s \n", it.key().data());
00168     }
00169   }
00170 #endif
00171 
00172 private:
00173   class MyMoneyMapAction
00174   {
00175     public:
00176       MyMoneyMapAction(QMap<Key, T>* container) :
00177         m_container(container) {}
00178 
00179       MyMoneyMapAction(QMap<Key, T>* container, const Key& key, const T& obj) :
00180         m_container(container),
00181         m_obj(obj),
00182         m_key(key) {}
00183 
00184       virtual ~MyMoneyMapAction() {}
00185       virtual void undo(void) = 0;
00186 
00187     protected:
00188       QMap<Key, T>* m_container;
00189       T m_obj;
00190       Key m_key;
00191   };
00192 
00193   class MyMoneyMapStart : public MyMoneyMapAction
00194   {
00195     public:
00196       MyMoneyMapStart(QMap<Key, T>* container, unsigned long* id) :
00197         MyMoneyMapAction(container),
00198         m_idPtr(id)
00199       {
00200         if(id != 0)
00201           m_id = *id;
00202       }
00203       virtual ~MyMoneyMapStart() {}
00204       void undo(void)
00205       {
00206         if(m_idPtr != 0)
00207           *m_idPtr = m_id;
00208       }
00209 
00210     private:
00211       unsigned long* m_idPtr;
00212       unsigned long  m_id;
00213   };
00214 
00215   class MyMoneyMapInsert : public MyMoneyMapAction
00216   {
00217     public:
00218       MyMoneyMapInsert(QMap<Key, T>* container, const Key& key, const T& obj) :
00219         MyMoneyMapAction(container, key, obj)
00220       {
00221         (*container)[key] = obj;
00222       }
00223 
00224       virtual ~MyMoneyMapInsert() {}
00225       void undo(void)
00226       {
00227         // m_container->remove(m_key) does not work on GCC 4.0.2
00228         // using this-> to access those member does the trick
00229         this->m_container->remove(this->m_key);
00230       }
00231   };
00232 
00233   class MyMoneyMapRemove : public MyMoneyMapAction
00234   {
00235     public:
00236       MyMoneyMapRemove(QMap<Key, T>* container, const Key& key) :
00237         MyMoneyMapAction(container, key, (*container)[key])
00238       {
00239         container->remove(key);
00240       }
00241 
00242       virtual ~MyMoneyMapRemove() {}
00243       void undo(void)
00244       {
00245         (*(this->m_container))[this->m_key] = this->m_obj;
00246       }
00247   };
00248 
00249   class MyMoneyMapModify : public MyMoneyMapAction
00250   {
00251     public:
00252       MyMoneyMapModify(QMap<Key, T>* container, const Key& key, const T& obj) :
00253         MyMoneyMapAction(container, key, (*container)[key])
00254       {
00255         (*container)[key] = obj;
00256       }
00257 
00258       virtual ~MyMoneyMapModify() {}
00259       void undo(void)
00260       {
00261         (*(this->m_container))[this->m_key] = this->m_obj;
00262       }
00263   };
00264 
00265 protected:
00266   QPtrStack<MyMoneyMapAction> m_stack;
00267 };
00268 
00269 #if MY_OWN_DEBUG
00270 #include <kmymoney/mymoneyaccount.h>
00271 #include <kmymoney/mymoneytransaction.h>
00272 main()
00273 {
00274   MyMoneyMap<QCString, MyMoneyAccount> container;
00275   MyMoneyMap<QCString, MyMoneyTransaction> ct;
00276 
00277   MyMoneyAccount acc;
00278   acc.setName("Test");
00279   // this should not be possible
00280   // container["a"] = acc;
00281 
00282   QValueList<MyMoneyAccount> list;
00283   list = container.values();
00284 
00285   MyMoneyAccount b;
00286   b.setName("Thomas");
00287 
00288   try {
00289     container.startTransaction();
00290     container.insert("001", acc);
00291     container.dump();
00292     container.commitTransaction();
00293     acc.setName("123");
00294     container.startTransaction();
00295     container.modify("001", acc);
00296     container.dump();
00297     container.rollbackTransaction();
00298     container.dump();
00299 
00300     container.startTransaction();
00301     container.remove(QCString("001"));
00302     container.dump();
00303     container.rollbackTransaction();
00304     container.dump();
00305 
00306     b = container["001"];
00307     printf("b.name() = %s\n", b.name().data());
00308 
00309     QMap<QCString, MyMoneyAccount>::ConstIterator it;
00310     it = container.find("001");
00311     it = container.begin();
00312 
00313   } catch(MyMoneyException *e) {
00314     printf("Caught exception: %s\n", e->what().data());
00315     delete e;
00316   }
00317 
00318   QMap<QCString, MyMoneyAccount> map;
00319   map["005"] = b;
00320   container = map;
00321 
00322   printf("b.name() = %s\n", container["001"].name().data());
00323   printf("b.name() = %s\n", container["005"].name().data());
00324 }
00325 
00326 #endif
00327 
00328 #endif

Generated on Mon Nov 17 11:59:19 2008 for KMyMoney by  doxygen 1.4.1