1 | /* |
2 | Copyright (c) 2008 Tobias Koenig <tokoe@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "entity.h" |
21 | #include "entity_p.h" |
22 | #include "collection.h" |
23 | |
24 | #include <kglobal.h> |
25 | |
26 | using namespace Akonadi; |
27 | |
28 | K_GLOBAL_STATIC(Akonadi::Collection, s_defaultParentCollection) |
29 | |
30 | /** |
31 | * Helper method for assignment operator and copy constructor. |
32 | */ |
33 | static void assignEntityPrivate(QSharedDataPointer<EntityPrivate> &one, const QSharedDataPointer<EntityPrivate> &other) |
34 | { |
35 | // We can't simply do one = other here, we have to use a temp. |
36 | // Otherwise ProtocolHelperTest::testParentCollectionAfterCollectionParsing() |
37 | // will break. |
38 | // |
39 | // The reason are assignments like |
40 | // col = col.parentCollection() |
41 | // |
42 | // Here, parentCollection() actually returns a reference to a pointer owned |
43 | // by col. So when col (or rather, it's private class) is deleted, the pointer |
44 | // to the parent collection and therefore the reference becomes invalid. |
45 | // |
46 | // With a single-line assignment here, the parent collection would be deleted |
47 | // before it is assigned, and therefore the resulting object would point to |
48 | // uninitalized memory. |
49 | QSharedDataPointer<EntityPrivate> temp = other; |
50 | one = temp; |
51 | } |
52 | |
53 | Entity::Entity(const Entity &other) |
54 | { |
55 | assignEntityPrivate(d_ptr, other.d_ptr); |
56 | } |
57 | |
58 | Entity::Entity(EntityPrivate *dd) |
59 | : d_ptr(dd) |
60 | { |
61 | } |
62 | |
63 | Entity::~Entity() |
64 | { |
65 | } |
66 | |
67 | void Entity::setId(Id id) |
68 | { |
69 | d_ptr->mId = id; |
70 | } |
71 | |
72 | Entity::Id Entity::id() const |
73 | { |
74 | return d_ptr->mId; |
75 | } |
76 | |
77 | void Entity::setRemoteId(const QString &id) |
78 | { |
79 | d_ptr->mRemoteId = id; |
80 | } |
81 | |
82 | QString Entity::remoteId() const |
83 | { |
84 | return d_ptr->mRemoteId; |
85 | } |
86 | |
87 | void Entity::setRemoteRevision(const QString &revision) |
88 | { |
89 | d_ptr->mRemoteRevision = revision; |
90 | } |
91 | |
92 | QString Entity::remoteRevision() const |
93 | { |
94 | return d_ptr->mRemoteRevision; |
95 | } |
96 | |
97 | bool Entity::isValid() const |
98 | { |
99 | return (d_ptr->mId >= 0); |
100 | } |
101 | |
102 | bool Entity::operator==(const Entity &other) const |
103 | { |
104 | // Invalid items are the same, no matter what their internal ID is |
105 | return (!isValid() && !other.isValid()) || (d_ptr->mId == other.d_ptr->mId); |
106 | } |
107 | |
108 | bool Akonadi::Entity::operator!=(const Entity &other) const |
109 | { |
110 | return (isValid() || other.isValid()) && (d_ptr->mId != other.d_ptr->mId); |
111 | } |
112 | |
113 | Entity &Entity ::operator=(const Entity &other) |
114 | { |
115 | if (this != &other) { |
116 | assignEntityPrivate(d_ptr, other.d_ptr); |
117 | } |
118 | |
119 | return *this; |
120 | } |
121 | |
122 | bool Akonadi::Entity::operator<(const Entity &other) const |
123 | { |
124 | return d_ptr->mId < other.d_ptr->mId; |
125 | } |
126 | |
127 | void Entity::addAttribute(Attribute *attr) |
128 | { |
129 | if (d_ptr->mAttributes.contains(attr->type())) { |
130 | Attribute *existing = d_ptr->mAttributes.value(attr->type()); |
131 | if (attr == existing) { |
132 | return; |
133 | } |
134 | d_ptr->mAttributes.remove(attr->type()); |
135 | delete existing; |
136 | } |
137 | d_ptr->mAttributes.insert(attr->type(), attr); |
138 | d_ptr->mDeletedAttributes.remove(attr->type()); |
139 | } |
140 | |
141 | void Entity::removeAttribute(const QByteArray &type) |
142 | { |
143 | d_ptr->mDeletedAttributes.insert(type); |
144 | delete d_ptr->mAttributes.take(type); |
145 | } |
146 | |
147 | bool Entity::hasAttribute(const QByteArray &type) const |
148 | { |
149 | return d_ptr->mAttributes.contains(type); |
150 | } |
151 | |
152 | Attribute::List Entity::attributes() const |
153 | { |
154 | return d_ptr->mAttributes.values(); |
155 | } |
156 | |
157 | void Akonadi::Entity::clearAttributes() |
158 | { |
159 | foreach (Attribute *attr, d_ptr->mAttributes) { |
160 | d_ptr->mDeletedAttributes.insert(attr->type()); |
161 | delete attr; |
162 | } |
163 | d_ptr->mAttributes.clear(); |
164 | } |
165 | |
166 | Attribute *Entity::attribute(const QByteArray &type) const |
167 | { |
168 | if (d_ptr->mAttributes.contains(type)) { |
169 | return d_ptr->mAttributes.value(type); |
170 | } |
171 | return 0; |
172 | } |
173 | |
174 | uint qHash(const Akonadi::Entity &entity) |
175 | { |
176 | return qHash(entity.id()); |
177 | } |
178 | |
179 | Collection &Entity::parentCollection() |
180 | { |
181 | if (!d_ptr->mParent) { |
182 | d_ptr->mParent = new Collection(); |
183 | } |
184 | return *(d_ptr->mParent); |
185 | } |
186 | |
187 | Collection Entity::parentCollection() const |
188 | { |
189 | if (!d_ptr->mParent) { |
190 | return *(s_defaultParentCollection); |
191 | } else { |
192 | return *(d_ptr->mParent); |
193 | } |
194 | } |
195 | |
196 | void Entity::setParentCollection(const Collection &parent) |
197 | { |
198 | delete d_ptr->mParent; |
199 | d_ptr->mParent = new Collection(parent); |
200 | } |
201 | |
202 | AKONADI_DEFINE_PRIVATE(Entity) |
203 | |