QxOrm  1.2.3
C++ Object Relational Mapping library
QxRepository.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** http://www.qxorm.com/
00004 ** http://sourceforge.net/projects/qxorm/
00005 ** Original file by Lionel Marty
00006 **
00007 ** This file is part of the QxOrm library
00008 **
00009 ** This software is provided 'as-is', without any express or implied
00010 ** warranty. In no event will the authors be held liable for any
00011 ** damages arising from the use of this software.
00012 **
00013 ** GNU Lesser General Public License Usage
00014 ** This file must be used under the terms of the GNU Lesser
00015 ** General Public License version 2.1 as published by the Free Software
00016 ** Foundation and appearing in the file 'license.lgpl.txt' included in the
00017 ** packaging of this file.  Please review the following information to
00018 ** ensure the GNU Lesser General Public License version 2.1 requirements
00019 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00020 **
00021 ** If you have questions regarding the use of this file, please contact :
00022 ** contact@qxorm.com
00023 **
00024 ****************************************************************************/
00025 
00026 #ifndef _QX_REPOSITORY_H_
00027 #define _QX_REPOSITORY_H_
00028 
00029 #ifdef _MSC_VER
00030 #pragma once
00031 #endif
00032 
00040 #include <boost/type_traits/is_base_of.hpp>
00041 
00042 #include <QxDao/QxRepository/IxRepository.h>
00043 #include <QxDao/QxRepository/QxRepositoryX.h>
00044 
00045 #include <QxDao/QxDao.h>
00046 #include <QxDao/QxSession.h>
00047 #include <QxDao/QxSqlError.h>
00048 
00049 #include <QxRegister/QxClass.h>
00050 
00051 #include <QxCollection/QxCollection.h>
00052 
00053 #include <QxTraits/get_primary_key.h>
00054 
00055 #define QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR   QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid collection pointer, dynamic_cast failed'", "", QSqlError::UnknownError)
00056 #define QX_REPOSITORY_POINTER_DYNAMIC_CAST_ERROR      QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid pointer, dynamic_cast failed'", "", QSqlError::UnknownError)
00057 #define QX_REPOSITORY_QOBJECT_BASE_CLASS_ERROR        QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid pointer, need to inherit from QObject class to use qx::IxRepository interface'", "", QSqlError::UnknownError)
00058 
00059 namespace qx {
00060 
00061 template <class T>
00062 inline void register_repository(const QString & sKey);
00063 
00068 template <class T>
00069 class QxRepository : public IxRepository
00070 {
00071 
00072    template <class U>
00073    friend inline void register_repository(const QString & sKey);
00074 
00075 private:
00076 
00077    QxRepository(const QString & sKey) : IxRepository(true, sKey) { ; }
00078 
00079 public:
00080 
00081    QxRepository() : IxRepository(false, QString("")) { ; }
00082    QxRepository(const QSqlDatabase & database) : IxRepository(false, QString(""), database) { ; }
00083    QxRepository(QxSession * pSession) : IxRepository(false, QString(""), pSession) { ; }
00084    virtual ~QxRepository() { ; }
00085 
00086    long count(const qx::QxSqlQuery & query = qx::QxSqlQuery())
00087    { return qx::dao::count<T>(query, this->database()); }
00088 
00089    T * fetchById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00090    {
00091       IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX();
00092       IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL);
00093       if (! pDataMemberId) { qAssert(false); return NULL; }
00094       T * t = new T(); QSqlError err;
00095       pDataMemberId->fromVariant(t, id);
00096       if (relation.count() == 0) { err = qx::dao::fetch_by_id((* t), this->database(), columns); }
00097       else { err = qx::dao::fetch_by_id_with_relation(relation, (* t), this->database()); }
00098       if (err.isValid() && m_pSession) { delete t; t = NULL; (* m_pSession) += err; }
00099       else if (err.isValid()) { delete t; t = NULL; }
00100       return t;
00101    }
00102 
00103    template <class U>
00104    QSqlError fetchById(U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00105    {
00106       QSqlError err;
00107       if (relation.count() == 0) { err = qx::dao::fetch_by_id(u, this->database(), columns); }
00108       else { err = qx::dao::fetch_by_id_with_relation(relation, u, this->database()); }
00109       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00110       return err;
00111    }
00112 
00113    template <class U>
00114    QSqlError fetchAll(U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00115    {
00116       QSqlError err;
00117       if (relation.count() == 0) { err = qx::dao::fetch_all(u, this->database(), columns); }
00118       else { err = qx::dao::fetch_all_with_relation(relation, u, this->database()); }
00119       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00120       return err;
00121    }
00122 
00123    template <class U>
00124    QSqlError fetchByQuery(const qx::QxSqlQuery & query, U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00125    {
00126       QSqlError err;
00127       if (relation.count() == 0) { err = qx::dao::fetch_by_query(query, u, this->database(), columns); }
00128       else { err = qx::dao::fetch_by_query_with_relation(relation, query, u, this->database()); }
00129       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00130       return err;
00131    }
00132 
00133    template <class U>
00134    QSqlError insert(U & u, const QStringList & relation = QStringList())
00135    {
00136       QSqlError err;
00137       if (relation.count() == 0) { err = qx::dao::insert(u, this->database()); }
00138       else { err = qx::dao::insert_with_relation(relation, u, this->database()); }
00139       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00140       return err;
00141    }
00142 
00143    template <class U>
00144    QSqlError update(U & u, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00145    {
00146       QSqlError err;
00147       if (relation.count() == 0) { err = qx::dao::update_by_query(query, u, this->database(), columns); }
00148       else { err = qx::dao::update_by_query_with_relation(relation, query, u, this->database()); }
00149       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00150       return err;
00151    }
00152 
00153    template <class U>
00154    QSqlError save(U & u, const QStringList & relation = QStringList())
00155    {
00156       QSqlError err;
00157       if (relation.count() == 0) { err = qx::dao::save(u, this->database()); }
00158       else { err = qx::dao::save_with_relation(relation, u, this->database()); }
00159       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00160       return err;
00161    }
00162 
00163    QSqlError deleteById(const QVariant & id)
00164    {
00165       IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX();
00166       IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL);
00167       if (! pDataMemberId) { qAssert(false); return QSqlError(); }
00168       boost::shared_ptr<T> t; t.reset(new T());
00169       pDataMemberId->fromVariant(t.get(), id);
00170       QSqlError err = qx::dao::delete_by_id((* t), this->database());
00171       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00172       return err;
00173    }
00174 
00175    template <class U>
00176    QSqlError deleteById(U & u)
00177    {
00178       QSqlError err = qx::dao::delete_by_id(u, this->database());
00179       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00180       return err;
00181    }
00182 
00183    QSqlError deleteAll()
00184    {
00185       QSqlError err = qx::dao::delete_all<T>(this->database());
00186       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00187       return err;
00188    }
00189 
00190    QSqlError deleteByQuery(const qx::QxSqlQuery & query)
00191    {
00192       QSqlError err = qx::dao::delete_by_query<T>(query, this->database());
00193       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00194       return err;
00195    }
00196 
00197    QSqlError destroyById(const QVariant & id)
00198    {
00199       IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX();
00200       IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL);
00201       if (! pDataMemberId) { qAssert(false); return QSqlError(); }
00202       boost::shared_ptr<T> t; t.reset(new T());
00203       pDataMemberId->fromVariant(t.get(), id);
00204       QSqlError err = qx::dao::destroy_by_id((* t), this->database());
00205       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00206       return err;
00207    }
00208 
00209    template <class U>
00210    QSqlError destroyById(U & u)
00211    {
00212       QSqlError err = qx::dao::destroy_by_id(u, this->database());
00213       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00214       return err;
00215    }
00216 
00217    QSqlError destroyAll()
00218    {
00219       QSqlError err = qx::dao::destroy_all<T>(this->database());
00220       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00221       return err;
00222    }
00223 
00224    QSqlError destroyByQuery(const qx::QxSqlQuery & query)
00225    {
00226       QSqlError err = qx::dao::destroy_by_query<T>(query, this->database());
00227       if (err.isValid() && m_pSession) { (* m_pSession) += err; }
00228       return err;
00229    }
00230 
00231    template <class U>
00232    qx_bool exist(U & u)
00233    { return qx::dao::exist(u, this->database()); }
00234 
00235 private:
00236 
00237    typedef typename qx::trait::get_primary_key<T>::type type_primary_key;
00238    typedef qx::QxCollection< type_primary_key, QSharedPointer<T> > type_collection_qt;
00239    typedef qx::QxCollection< type_primary_key, boost::shared_ptr<T> > type_collection_boost;
00240 
00241    template <bool bIsQObject /* = false */, int dummy>
00242    struct qxVerifyPointer
00243    { static inline T * get(QObject * p) { Q_UNUSED(p); throw qx::dao::sql_error(QX_REPOSITORY_QOBJECT_BASE_CLASS_ERROR); return NULL; } };
00244 
00245    template <int dummy>
00246    struct qxVerifyPointer<true, dummy>
00247    { static inline T * get(QObject * p) { T * t = dynamic_cast<T *>(p); if (! t) { throw qx::dao::sql_error(QX_REPOSITORY_POINTER_DYNAMIC_CAST_ERROR); }; return t; } };
00248 
00249 public:
00250 
00251    virtual long _count(const qx::QxSqlQuery & query = qx::QxSqlQuery())
00252    { return this->count(query); }
00253 
00254    virtual void * _fetchById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00255    { return static_cast<void *>(this->fetchById(id, columns, relation)); }
00256 
00257    virtual QSqlError _fetchById(QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00258    {
00259       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00260       return this->fetchById((* t), columns, relation);
00261    }
00262 
00263    virtual QSqlError _fetchById(qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00264    {
00265       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00266       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00267       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00268       return (x ? this->fetchById((* x), columns, relation) : this->fetchById((* y), columns, relation));
00269    }
00270 
00271    virtual QSqlError _fetchAll(QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00272    {
00273       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00274       return this->fetchAll((* t), columns, relation);
00275    }
00276 
00277    virtual QSqlError _fetchAll(qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00278    {
00279       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00280       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00281       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00282       return (x ? this->fetchAll((* x), columns, relation) : this->fetchAll((* y), columns, relation));
00283    }
00284 
00285    virtual QSqlError _fetchByQuery(const qx::QxSqlQuery & query, QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00286    {
00287       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00288       return this->fetchByQuery(query, (* t), columns, relation);
00289    }
00290 
00291    virtual QSqlError _fetchByQuery(const qx::QxSqlQuery & query, qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00292    {
00293       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00294       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00295       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00296       return (x ? this->fetchByQuery(query, (* x), columns, relation) : this->fetchByQuery(query, (* y), columns, relation));
00297    }
00298 
00299    virtual QSqlError _insert(QObject * p, const QStringList & relation = QStringList())
00300    {
00301       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00302       return this->insert((* t), relation);
00303    }
00304 
00305    virtual QSqlError _insert(qx::IxCollection * p, const QStringList & relation = QStringList())
00306    {
00307       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00308       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00309       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00310       return (x ? this->insert((* x), relation) : this->insert((* y), relation));
00311    }
00312 
00313    virtual QSqlError _update(QObject * p, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00314    {
00315       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00316       return this->update((* t), query, columns, relation);
00317    }
00318 
00319    virtual QSqlError _update(qx::IxCollection * p, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00320    {
00321       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00322       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00323       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00324       return (x ? this->update((* x), query, columns, relation) : this->update((* y), query, columns, relation));
00325    }
00326 
00327    virtual QSqlError _save(QObject * p, const QStringList & relation = QStringList())
00328    {
00329       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00330       return this->save((* t), relation);
00331    }
00332 
00333    virtual QSqlError _save(qx::IxCollection * p, const QStringList & relation = QStringList())
00334    {
00335       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00336       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00337       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00338       return (x ? this->save((* x), relation) : this->save((* y), relation));
00339    }
00340 
00341    virtual QSqlError _deleteById(const QVariant & id)
00342    { return this->deleteById(id); }
00343 
00344    virtual QSqlError _deleteById(QObject * p)
00345    {
00346       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00347       return this->deleteById(* t);
00348    }
00349 
00350    virtual QSqlError _deleteById(qx::IxCollection * p)
00351    {
00352       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00353       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00354       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00355       return (x ? this->deleteById(* x) : this->deleteById(* y));
00356    }
00357 
00358    virtual QSqlError _deleteAll()
00359    { return this->deleteAll(); }
00360 
00361    virtual QSqlError _deleteByQuery(const qx::QxSqlQuery & query)
00362    { return this->deleteByQuery(query); }
00363 
00364    virtual QSqlError _destroyById(const QVariant & id)
00365    { return this->destroyById(id); }
00366 
00367    virtual QSqlError _destroyById(QObject * p)
00368    {
00369       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00370       return this->destroyById(* t);
00371    }
00372 
00373    virtual QSqlError _destroyById(qx::IxCollection * p)
00374    {
00375       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00376       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00377       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00378       return (x ? this->destroyById(* x) : this->destroyById(* y));
00379    }
00380 
00381    virtual QSqlError _destroyAll()
00382    { return this->destroyAll(); }
00383 
00384    virtual QSqlError _destroyByQuery(const qx::QxSqlQuery & query)
00385    { return this->destroyByQuery(query); }
00386 
00387    virtual qx_bool _exist(QObject * p)
00388    {
00389       T * t = qxVerifyPointer<boost::is_base_of<QObject, T>::value, 0>::get(p);
00390       return this->exist(* t);
00391    }
00392 
00393    virtual qx_bool _exist(qx::IxCollection * p)
00394    {
00395       type_collection_qt * x = dynamic_cast<type_collection_qt *>(p);
00396       type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p));
00397       if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); }
00398       return (x ? this->exist(* x) : this->exist(* y));
00399    }
00400 
00401    virtual qx::IxCollection_ptr _newCollection() const
00402    {
00403       qx::IxCollection_ptr lst;
00404       lst.reset(new type_collection_boost());
00405       return lst;
00406    }
00407 
00408    virtual qx::IxClass * _getClass() const
00409    { return qx::QxClass<T>::getSingleton(); }
00410 
00411 public:
00412 
00413    static T * getById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList())
00414    {
00415       IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX();
00416       IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL);
00417       if (! pDataMemberId) { qAssert(false); return NULL; }
00418       T * t = new T(); QSqlError err;
00419       pDataMemberId->fromVariant(t, id);
00420       if (relation.count() == 0) { err = qx::dao::fetch_by_id((* t), NULL, columns); }
00421       else { err = qx::dao::fetch_by_id_with_relation(relation, (* t), NULL); }
00422       if (err.isValid()) { delete t; t = NULL; }
00423       return t;
00424    }
00425 
00426 };
00427 
00428 template <class T>
00429 inline void register_repository(const QString & sKey)
00430 {
00431    // 'pNewRepository' instance will be destroyed by 'qx::QxRepositoryX::unregisterRepository()' method
00432    qx::QxRepository<T> * pNewRepository = new qx::QxRepository<T>(sKey);
00433    Q_UNUSED(pNewRepository);
00434 }
00435 
00436 } // namespace qx
00437 
00438 #endif // _QX_REPOSITORY_H_