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
26using namespace Akonadi;
27
28K_GLOBAL_STATIC(Akonadi::Collection, s_defaultParentCollection)
29
30/**
31 * Helper method for assignment operator and copy constructor.
32 */
33static 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
53Entity::Entity(const Entity &other)
54{
55 assignEntityPrivate(d_ptr, other.d_ptr);
56}
57
58Entity::Entity(EntityPrivate *dd)
59 : d_ptr(dd)
60{
61}
62
63Entity::~Entity()
64{
65}
66
67void Entity::setId(Id id)
68{
69 d_ptr->mId = id;
70}
71
72Entity::Id Entity::id() const
73{
74 return d_ptr->mId;
75}
76
77void Entity::setRemoteId(const QString &id)
78{
79 d_ptr->mRemoteId = id;
80}
81
82QString Entity::remoteId() const
83{
84 return d_ptr->mRemoteId;
85}
86
87void Entity::setRemoteRevision(const QString &revision)
88{
89 d_ptr->mRemoteRevision = revision;
90}
91
92QString Entity::remoteRevision() const
93{
94 return d_ptr->mRemoteRevision;
95}
96
97bool Entity::isValid() const
98{
99 return (d_ptr->mId >= 0);
100}
101
102bool 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
108bool Akonadi::Entity::operator!=(const Entity &other) const
109{
110 return (isValid() || other.isValid()) && (d_ptr->mId != other.d_ptr->mId);
111}
112
113Entity &Entity ::operator=(const Entity &other)
114{
115 if (this != &other) {
116 assignEntityPrivate(d_ptr, other.d_ptr);
117 }
118
119 return *this;
120}
121
122bool Akonadi::Entity::operator<(const Entity &other) const
123{
124 return d_ptr->mId < other.d_ptr->mId;
125}
126
127void 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
141void Entity::removeAttribute(const QByteArray &type)
142{
143 d_ptr->mDeletedAttributes.insert(type);
144 delete d_ptr->mAttributes.take(type);
145}
146
147bool Entity::hasAttribute(const QByteArray &type) const
148{
149 return d_ptr->mAttributes.contains(type);
150}
151
152Attribute::List Entity::attributes() const
153{
154 return d_ptr->mAttributes.values();
155}
156
157void 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
166Attribute *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
174uint qHash(const Akonadi::Entity &entity)
175{
176 return qHash(entity.id());
177}
178
179Collection &Entity::parentCollection()
180{
181 if (!d_ptr->mParent) {
182 d_ptr->mParent = new Collection();
183 }
184 return *(d_ptr->mParent);
185}
186
187Collection Entity::parentCollection() const
188{
189 if (!d_ptr->mParent) {
190 return *(s_defaultParentCollection);
191 } else {
192 return *(d_ptr->mParent);
193 }
194}
195
196void Entity::setParentCollection(const Collection &parent)
197{
198 delete d_ptr->mParent;
199 d_ptr->mParent = new Collection(parent);
200}
201
202AKONADI_DEFINE_PRIVATE(Entity)
203