1/***************************************************************************
2 * Copyright (C) 2006 by Andreas Gungl <a.gungl@gmx.de> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU Library General Public License as *
6 * published by the Free Software Foundation; either version 2 of the *
7 * License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Library General Public *
15 * License along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19
20#ifndef ENTITY_H
21#define ENTITY_H
22
23#include <QtCore/Qt>
24#include <QtCore/QDateTime>
25#include <QtCore/QDebug>
26#include <QtCore/QString>
27#include <QtCore/QStringList>
28
29class QVariant;
30class QSqlDatabase;
31
32namespace Akonadi {
33namespace Server {
34
35enum Tristate {
36 False = 0,
37 True = 1,
38 Undefined = 2
39};
40
41/**
42 Base class for classes representing database records. It also contains
43 low-level data access and manipulation template methods.
44*/
45class Entity
46{
47public:
48 typedef qint64 Id;
49
50protected:
51 qint64 id() const;
52 void setId(qint64 id);
53
54 bool isValid() const;
55
56public:
57 template <typename T> static QString joinByName(const QVector<T> &list, const QString &sep)
58 {
59 QStringList tmp;
60 Q_FOREACH (const T &t, list) {
61 tmp << t.name();
62 }
63 return tmp.join(sep);
64 }
65
66 /**
67 Returns the number of records having @p value in @p column.
68 @param column The name of the key column.
69 @param value The value used to identify the record.
70 */
71 template <typename T> inline static int count(const QString &column, const QVariant &value)
72 {
73 return Entity::countImpl(T::tableName(), column, value);
74 }
75
76 /**
77 Deletes all records having @p value in @p column.
78 */
79 template <typename T> inline static bool remove(const QString &column, const QVariant &value)
80 {
81 return Entity::removeImpl(T::tableName(), column, value);
82 }
83
84 /**
85 Checks whether an entry in a n:m relation table exists.
86 @param leftId Identifier of the left part of the relation.
87 @param rightId Identifier of the right part of the relation.
88 */
89 template <typename T> inline static bool relatesTo(qint64 leftId, qint64 rightId)
90 {
91 return Entity::relatesToImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
92 }
93
94 /**
95 Adds an entry to a n:m relation table (specified by the template parameter).
96 @param leftId Identifier of the left part of the relation.
97 @param rightId Identifier of the right part of the relation.
98 */
99 template <typename T> inline static bool addToRelation(qint64 leftId, qint64 rightId)
100 {
101 return Entity::addToRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
102 }
103
104 /**
105 Removes an entry from a n:m relation table (specified by the template parameter).
106 @param leftId Identifier of the left part of the relation.
107 @param rightId Identifier of the right part of the relation.
108 */
109 template <typename T> inline static bool removeFromRelation(qint64 leftId, qint64 rightId)
110 {
111 return Entity::removeFromRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId);
112 }
113
114 enum RelationSide {
115 Left,
116 Right
117 };
118
119 /**
120 Clears all entries from a n:m relation table (specified by the given template parameter).
121 @param id Identifier on the relation side.
122 @param side The side of the relation.
123 */
124 template <typename T> inline static bool clearRelation(qint64 id, RelationSide side = Left)
125 {
126 return Entity::clearRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), id, side);
127 }
128
129protected:
130 Entity();
131 explicit Entity(qint64 id);
132 ~Entity();
133
134private:
135 static int countImpl(const QString &tableName, const QString &column, const QVariant &value);
136 static bool removeImpl(const QString &tableName, const QString &column, const QVariant &value);
137 static bool relatesToImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
138 static bool addToRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
139 static bool removeFromRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId);
140 static bool clearRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 id, RelationSide side);
141
142private:
143 static QSqlDatabase database();
144 qint64 m_id;
145};
146
147namespace _detail {
148
149/*!
150 Binary predicate to sort collections of Entity subclasses by
151 their id.
152
153 Example for sorting:
154 \code
155 std::sort( coll.begin(), coll.end(), _detail::ById<std::less>() );
156 \endcode
157
158 Example for finding by id:
159 \code
160 // linear:
161 std::find_if( coll.begin(), coll.end(), bind( _detail::ById<std::equal_to>(), _1, myId ) );
162 // binary:
163 std::lower_bound( coll.begin(), coll.end(), myId, _detail::ById<std::less>() );
164 \end
165*/
166template <template <typename U> class Op>
167struct ById {
168 typedef bool result_type;
169 bool operator()(Entity::Id lhs, Entity::Id rhs) const
170 {
171 return Op<Entity::Id>()(lhs, rhs);
172 }
173 template <typename E>
174 bool operator()(const E &lhs, const E &rhs) const
175 {
176 return this->operator()(lhs.id() , rhs.id());
177 }
178 template <typename E>
179 bool operator()(const E &lhs, Entity::Id rhs) const
180 {
181 return this->operator()(lhs.id(), rhs);
182 }
183 template <typename E>
184 bool operator()(Entity::Id lhs, const E &rhs) const
185 {
186 return this->operator()(lhs, rhs.id());
187 }
188};
189}
190
191} // namespace Server
192} // namespace Akonadi
193
194Q_DECLARE_METATYPE(Akonadi::Server::Tristate)
195
196#endif
197