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