File indexing completed on 2025-01-05 04:46:58

0001 /***************************************************************************
0002  *   SPDX-FileCopyrightText: 2006 Andreas Gungl <a.gungl@gmx.de>           *
0003  *                                                                         *
0004  *   SPDX-License-Identifier: LGPL-2.0-or-later                            *
0005  ***************************************************************************/
0006 
0007 #pragma once
0008 
0009 #include <QString>
0010 #include <QStringList>
0011 
0012 class QVariant;
0013 
0014 namespace Akonadi
0015 {
0016 namespace Server
0017 {
0018 class DataStore;
0019 /**
0020   Base class for classes representing database records. It also contains
0021   low-level data access and manipulation template methods.
0022 */
0023 class Entity
0024 {
0025 public:
0026     using Id = qint64;
0027 
0028 protected:
0029     qint64 id() const;
0030     void setId(qint64 id);
0031 
0032     bool isValid() const;
0033 
0034 public:
0035     template<typename T>
0036     static QString joinByName(const QList<T> &list, const QString &sep)
0037     {
0038         QStringList tmp;
0039         tmp.reserve(list.count());
0040         for (const T &t : list) {
0041             tmp << t.name();
0042         }
0043         return tmp.join(sep);
0044     }
0045 
0046     /**
0047       Returns the number of records having @p value in @p column.
0048       @param column The name of the key column.
0049       @param value The value used to identify the record.
0050     */
0051     template<typename T>
0052     inline static int count(const QString &column, const QVariant &value)
0053     {
0054         return count<T>(dataStore(), column, value);
0055     }
0056 
0057     template<typename T>
0058     inline static int count(DataStore *store, const QString &column, const QVariant &value)
0059     {
0060         return Entity::countImpl(store, T::tableName(), column, value);
0061     }
0062 
0063     /**
0064       Deletes all records having @p value in @p column.
0065     */
0066     template<typename T>
0067     inline static bool remove(const QString &column, const QVariant &value)
0068     {
0069         return remove<T>(dataStore(), column, value);
0070     }
0071 
0072     template<typename T>
0073     inline static bool remove(DataStore *store, const QString &column, const QVariant &value)
0074     {
0075         return Entity::removeImpl(store, T::tableName(), column, value);
0076     }
0077 
0078     /**
0079       Checks whether an entry in a n:m relation table exists.
0080       @param leftId Identifier of the left part of the relation.
0081       @param rightId Identifier of the right part of the relation.
0082      */
0083     template<typename T>
0084     inline static bool relatesTo(qint64 leftId, qint64 rightId)
0085     {
0086         return relatesTo<T>(dataStore(), leftId, rightId);
0087     }
0088 
0089     template<typename T>
0090     inline static bool relatesTo(DataStore *store, qint64 leftId, qint64 rightId)
0091     {
0092         return Entity::relatesToImpl(store, T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
0093     }
0094 
0095     /**
0096       Adds an entry to a n:m relation table (specified by the template parameter).
0097       @param leftId Identifier of the left part of the relation.
0098       @param rightId Identifier of the right part of the relation.
0099     */
0100     template<typename T>
0101     inline static bool addToRelation(qint64 leftId, qint64 rightId)
0102     {
0103         return addToRelation<T>(dataStore(), leftId, rightId);
0104     }
0105 
0106     template<typename T>
0107     inline static bool addToRelation(DataStore *store, qint64 leftId, qint64 rightId)
0108     {
0109         return Entity::addToRelationImpl(store, T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
0110     }
0111 
0112     /**
0113       Removes an entry from a n:m relation table (specified by the template parameter).
0114       @param leftId Identifier of the left part of the relation.
0115       @param rightId Identifier of the right part of the relation.
0116     */
0117     template<typename T>
0118     inline static bool removeFromRelation(qint64 leftId, qint64 rightId)
0119     {
0120         return removeFromRelation<T>(dataStore(), leftId, rightId);
0121     }
0122 
0123     template<typename T>
0124     inline static bool removeFromRelation(DataStore *store, qint64 leftId, qint64 rightId)
0125     {
0126         return Entity::removeFromRelationImpl(store, T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
0127     }
0128 
0129     enum RelationSide {
0130         Left,
0131         Right,
0132     };
0133 
0134     /**
0135       Clears all entries from a n:m relation table (specified by the given template parameter).
0136       @param id Identifier on the relation side.
0137       @param side The side of the relation.
0138     */
0139     template<typename T>
0140     inline static bool clearRelation(qint64 id, RelationSide side = Left)
0141     {
0142         return clearRelation<T>(dataStore(), id, side);
0143     }
0144     template<typename T>
0145     inline static bool clearRelation(DataStore *store, qint64 id, RelationSide side = Left)
0146     {
0147         return Entity::clearRelationImpl(store, T::tableName(), T::leftColumn(), T::rightColumn(), id, side);
0148     }
0149 
0150 protected:
0151     Entity();
0152     explicit Entity(qint64 id);
0153     ~Entity();
0154 
0155 private:
0156     static DataStore *dataStore();
0157 
0158     static int countImpl(DataStore *store, const QString &tableName, const QString &column, const QVariant &value);
0159     static bool removeImpl(DataStore *store, const QString &tableName, const QString &column, const QVariant &value);
0160     static bool relatesToImpl(DataStore *store, const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
0161     static bool
0162     addToRelationImpl(DataStore *store, const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
0163     static bool
0164     removeFromRelationImpl(DataStore *store, const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
0165     static bool
0166     clearRelationImpl(DataStore *store, const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 id, RelationSide side);
0167 
0168 private:
0169     qint64 m_id;
0170 };
0171 
0172 namespace _detail
0173 {
0174 /*!
0175   Binary predicate to sort collections of Entity subclasses by
0176   their id.
0177 
0178   Example for sorting:
0179   \code
0180   std::sort( coll.begin(), coll.end(), _detail::ById<std::less>() );
0181   \endcode
0182 
0183   Example for finding by id:
0184   \code
0185   // linear:
0186   std::find_if( coll.begin(), coll.end(), bind( _detail::ById<std::equal_to>(), _1, myId ) );
0187   // binary:
0188   std::lower_bound( coll.begin(), coll.end(), myId, _detail::ById<std::less>() );
0189   \endcode
0190 */
0191 template<template<typename U> class Op>
0192 struct ById {
0193     using result_type = bool;
0194     bool operator()(Entity::Id lhs, Entity::Id rhs) const
0195     {
0196         return Op<Entity::Id>()(lhs, rhs);
0197     }
0198     template<typename E>
0199     bool operator()(const E &lhs, const E &rhs) const
0200     {
0201         return this->operator()(lhs.id(), rhs.id());
0202     }
0203     template<typename E>
0204     bool operator()(const E &lhs, Entity::Id rhs) const
0205     {
0206         return this->operator()(lhs.id(), rhs);
0207     }
0208     template<typename E>
0209     bool operator()(Entity::Id lhs, const E &rhs) const
0210     {
0211         return this->operator()(lhs, rhs.id());
0212     }
0213 };
0214 }
0215 
0216 } // namespace Server
0217 } // namespace Akonadi