~renatofilho/buteo-sync-plugins-contacts/solve-eds-conflict

« back to all changes in this revision

Viewing changes to tests/plugins/contacts/qcontactmemorybackend.cpp

  • Committer: CI Train Bot
  • Author(s): Renato Araujo Oliveira Filho
  • Date: 2015-09-24 17:50:44 UTC
  • mfrom: (1.3.53 initial-vr)
  • Revision ID: ci-train-bot@canonical.com-20150924175044-rp0akjs0h1xwxmpj
Implemented buteo contacts sync plugin for google, heavily based on:
  - https://github.com/nemomobile-graveyard/buteo-sync-plugins-google
  - https://github.com/nemomobile/buteo-sync-plugins-social
Approved by: Michael Sheldon

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtContacts module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qcontactmemorybackend_p.h"
 
43
 
 
44
#ifndef QT_NO_DEBUG_STREAM
 
45
#include <QtCore/qdebug.h>
 
46
#endif
 
47
#include <QtCore/qpointer.h>
 
48
#include <QtCore/qstringbuilder.h>
 
49
#include <QtCore/quuid.h>
 
50
 
 
51
#include <QtContacts/qcontactidfilter.h>
 
52
#include <QtContacts/qcontactrequests.h>
 
53
#include <QtContacts/qcontacttimestamp.h>
 
54
#include <QtContacts/qcontactextendeddetail.h>
 
55
#include <QtContacts/qcontactchangelogfilter.h>
 
56
#include <QtContacts/qcontactintersectionfilter.h>
 
57
#include <QtContacts/qcontactunionfilter.h>
 
58
#include <QtContacts/qcontacttimestamp.h>
 
59
 
 
60
#define ENGINE_NAME     "mock"
 
61
#define X_DELETED_AT    "X-DELETED-AT"
 
62
 
 
63
QT_BEGIN_NAMESPACE_CONTACTS
 
64
 
 
65
QContactManagerEngine* QContactMemoryEngineFactory::engine(const QMap<QString, QString> &parameters, QContactManager::Error *error)
 
66
{
 
67
    Q_UNUSED(error);
 
68
 
 
69
    QContactMemoryEngine *ret = QContactMemoryEngine::createMemoryEngine(parameters);
 
70
    return ret;
 
71
}
 
72
 
 
73
 
 
74
QContactEngineId* QContactMemoryEngineFactory::createContactEngineId(const QMap<QString, QString> &parameters, const QString &engineIdString) const
 
75
{
 
76
    Q_UNUSED(parameters);
 
77
    QContactMemoryEngineId *retn = new QContactMemoryEngineId(parameters, engineIdString);
 
78
    return retn;
 
79
}
 
80
 
 
81
QString QContactMemoryEngineFactory::managerName() const
 
82
{
 
83
    return QString::fromLatin1(ENGINE_NAME);
 
84
}
 
85
 
 
86
/*!
 
87
  \class QContactMemoryEngine
 
88
 
 
89
  \inmodule QtContacts
 
90
 
 
91
  \brief The QContactMemoryEngine class provides an in-memory implementation
 
92
  of a contacts backend.
 
93
 
 
94
  \internal
 
95
 
 
96
  It may be used as a reference implementation, or when persistent storage is not required.
 
97
 
 
98
  During construction, it will load the in-memory data associated with the memory store
 
99
  identified by the "id" parameter from the given parameters if it exists, or a new,
 
100
  anonymous store if it does not.
 
101
 
 
102
  Data stored in this engine is only available in the current process.
 
103
 
 
104
  This engine supports sharing, so an internal reference count is increased
 
105
  whenever a manager uses this backend, and is decreased when the manager
 
106
  no longer requires this engine.
 
107
 */
 
108
 
 
109
/* static data for manager class */
 
110
QMap<QString, QContactMemoryEngineData*> QContactMemoryEngine::engineDatas;
 
111
 
 
112
/*!
 
113
 * Factory function for creating a new in-memory backend, based
 
114
 * on the given \a parameters.
 
115
 *
 
116
 * The same engine will be returned for multiple calls with the
 
117
 * same value for the "id" parameter, while one of them is in scope.
 
118
 */
 
119
QContactMemoryEngine* QContactMemoryEngine::createMemoryEngine(const QMap<QString, QString> &parameters)
 
120
{
 
121
    bool anonymous = false;
 
122
    QString idValue = parameters.value(QStringLiteral("id"));
 
123
    if (idValue.isNull() || idValue.isEmpty()) {
 
124
        // no store given?  new, anonymous store.
 
125
        idValue = "mock"; //QUuid::createUuid().toString();
 
126
        anonymous = true;
 
127
    }
 
128
 
 
129
    QContactMemoryEngineData *data = engineDatas.value(idValue);
 
130
    if (data) {
 
131
        data->m_refCount.ref();
 
132
    } else {
 
133
        data = new QContactMemoryEngineData();
 
134
        data->m_id = idValue;
 
135
        data->m_anonymous = anonymous;
 
136
        engineDatas.insert(idValue, data);
 
137
    }
 
138
    return new QContactMemoryEngine(data);
 
139
}
 
140
 
 
141
/*!
 
142
 * Constructs a new in-memory backend which shares the given \a data with
 
143
 * other shared memory engines.
 
144
 */
 
145
QContactMemoryEngine::QContactMemoryEngine(QContactMemoryEngineData *data)
 
146
    : d(data)
 
147
{
 
148
    qRegisterMetaType<QContactAbstractRequest::State>("QContactAbstractRequest::State");
 
149
    qRegisterMetaType<QList<QContactId> >("QList<QContactId>");
 
150
    qRegisterMetaType<QContactId>("QContactId");
 
151
    d->m_managerUri = managerUri();
 
152
    d->m_sharedEngines.append(this);
 
153
}
 
154
 
 
155
/*! Frees any memory used by this engine */
 
156
QContactMemoryEngine::~QContactMemoryEngine()
 
157
{
 
158
    d->m_sharedEngines.removeAll(this);
 
159
    if (!d->m_refCount.deref()) {
 
160
        engineDatas.remove(d->m_id);
 
161
        delete d;
 
162
    }
 
163
}
 
164
 
 
165
/*! \reimp */
 
166
QString QContactMemoryEngine::managerName() const
 
167
{
 
168
    return QStringLiteral(ENGINE_NAME);
 
169
}
 
170
 
 
171
/*! \reimp */
 
172
QMap<QString, QString> QContactMemoryEngine::managerParameters() const
 
173
{
 
174
    QMap<QString, QString> params;
 
175
    params.insert(QStringLiteral("id"), d->m_id);
 
176
    return params;
 
177
}
 
178
 
 
179
/*! \reimp */
 
180
bool QContactMemoryEngine::setSelfContactId(const QContactId &contactId, QContactManager::Error *error)
 
181
{
 
182
    if (contactId.isNull() || d->m_contactIds.contains(contactId)) {
 
183
        *error = QContactManager::NoError;
 
184
        QContactId oldId = d->m_selfContactId;
 
185
        d->m_selfContactId = contactId;
 
186
 
 
187
        QContactChangeSet changeSet;
 
188
        changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(oldId, contactId));
 
189
        d->emitSharedSignals(&changeSet);
 
190
        return true;
 
191
    }
 
192
 
 
193
    *error = QContactManager::DoesNotExistError;
 
194
    return false;
 
195
}
 
196
 
 
197
/*! \reimp */
 
198
QContactId QContactMemoryEngine::selfContactId(QContactManager::Error *error) const
 
199
{
 
200
    *error = QContactManager::DoesNotExistError;
 
201
    if (!d->m_selfContactId.isNull())
 
202
        *error = QContactManager::NoError;
 
203
    return d->m_selfContactId;
 
204
}
 
205
 
 
206
/*! \reimp */
 
207
QContact QContactMemoryEngine::contact(const QContactId &contactId, const QContactFetchHint &fetchHint, QContactManager::Error *error) const
 
208
{
 
209
    Q_UNUSED(fetchHint); // no optimizations are possible in the memory backend; ignore the fetch hint.
 
210
    int index = d->m_contactIds.indexOf(contactId);
 
211
    if (index != -1) {
 
212
        // found the contact successfully.
 
213
        *error = QContactManager::NoError;
 
214
        return d->m_contacts.at(index);
 
215
    }
 
216
 
 
217
    *error = QContactManager::DoesNotExistError;
 
218
    return QContact();
 
219
}
 
220
 
 
221
/*! \reimp */
 
222
QList<QContactId> QContactMemoryEngine::contactIds(const QContactFilter &filter, const QList<QContactSortOrder> &sortOrders, QContactManager::Error *error) const
 
223
{
 
224
    QList<QContact> clist = contacts(filter, sortOrders, QContactFetchHint(), error);
 
225
 
 
226
    /* Extract the ids */
 
227
    QList<QContactId> ids;
 
228
    foreach (const QContact &c, clist)
 
229
        ids.append(c.id());
 
230
 
 
231
    return ids;
 
232
}
 
233
 
 
234
bool QContactMemoryEngine::testDeletedContact(const QContactFilter &filter,
 
235
                                              const QContact &contact,
 
236
                                              const QDateTime &deletedAt) const
 
237
{
 
238
    switch(filter.type()) {
 
239
    case QContactFilter::ChangeLogFilter:
 
240
    {
 
241
        const QContactChangeLogFilter bf(filter);
 
242
        if (bf.eventType() == QContactChangeLogFilter::EventRemoved) {
 
243
            return (deletedAt >= bf.since());
 
244
        }
 
245
        break;
 
246
    }
 
247
    case QContactFilter::IdFilter:
 
248
    {
 
249
        const QContactIdFilter idF(filter);
 
250
        return (idF.ids().contains(contact.id()));
 
251
    }
 
252
    case QContactFilter::IntersectionFilter:
 
253
    {
 
254
        const QContactIntersectionFilter bf(filter);
 
255
        const QList<QContactFilter>& terms = bf.filters();
 
256
        if (terms.count() > 0) {
 
257
            bool changeLogResult = false;
 
258
            for(int j = 0; j < terms.count(); j++) {
 
259
                if (terms.at(j).type() == QContactFilter::ChangeLogFilter) {
 
260
                    changeLogResult = testDeletedContact(terms.at(j), contact, deletedAt);
 
261
                } else if (!QContactManagerEngine::testFilter(terms.at(j), contact)) {
 
262
                    return false;
 
263
                }
 
264
            }
 
265
            return changeLogResult;
 
266
        }
 
267
        break;
 
268
    }
 
269
    case QContactFilter::UnionFilter:
 
270
    {
 
271
        return QContactManagerEngine::testFilter(filter, contact);
 
272
    }
 
273
    default:
 
274
        break;
 
275
    }
 
276
    return false;
 
277
}
 
278
 
 
279
/*! \reimp */
 
280
QList<QContact> QContactMemoryEngine::contacts(const QContactFilter &filter, const QList<QContactSortOrder> &sortOrders, const QContactFetchHint &fetchHint, QContactManager::Error *error) const
 
281
{
 
282
    Q_UNUSED(fetchHint); // no optimizations are possible in the memory backend; ignore the fetch hint.
 
283
    Q_UNUSED(error);
 
284
 
 
285
    QList<QContact> sorted;
 
286
 
 
287
    /* First filter out contacts - check for default filter first */
 
288
    if (filter.type() == QContactFilter::DefaultFilter) {
 
289
        foreach(const QContact&c, d->m_contacts) {
 
290
            if (!deleted(c).isValid())
 
291
                QContactManagerEngine::addSorted(&sorted,c, sortOrders);
 
292
        }
 
293
    } else {
 
294
        foreach(const QContact&c, d->m_contacts) {
 
295
            QDateTime deletedAt = deleted(c);
 
296
            if (deletedAt.isValid() && testDeletedContact(filter, c, deletedAt))
 
297
                QContactManagerEngine::addSorted(&sorted,c, sortOrders);
 
298
            else if (!deletedAt.isValid() && QContactManagerEngine::testFilter(filter, c))
 
299
                QContactManagerEngine::addSorted(&sorted,c, sortOrders);
 
300
        }
 
301
    }
 
302
 
 
303
    return sorted;
 
304
}
 
305
 
 
306
/*! Saves the given contact \a theContact, storing any error to \a error and
 
307
    filling the \a changeSet with ids of changed contacts as required
 
308
    Returns true if the operation was successful otherwise false.
 
309
*/
 
310
bool QContactMemoryEngine::saveContact(QContact *theContact, QContactChangeSet &changeSet, QContactManager::Error *error)
 
311
{
 
312
    return saveContact(theContact, changeSet, error, QList<QContactDetail::DetailType>());
 
313
}
 
314
 
 
315
/*! \reimp */
 
316
bool QContactMemoryEngine::saveContacts(QList<QContact> *contacts, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
 
317
{
 
318
    return saveContacts(contacts, errorMap, error, QList<QContactDetail::DetailType>());
 
319
}
 
320
 
 
321
/*! Removes the contact identified by the given \a contactId, storing any error to \a error and
 
322
    filling the \a changeSet with ids of changed contacts and relationships as required.
 
323
    Returns true if the operation was successful otherwise false.
 
324
*/
 
325
bool QContactMemoryEngine::removeContact(const QContactId &contactId, QContactChangeSet &changeSet, QContactManager::Error *error)
 
326
{
 
327
    int index = d->m_contactIds.indexOf(contactId);
 
328
 
 
329
    if (index == -1) {
 
330
        *error = QContactManager::DoesNotExistError;
 
331
        return false;
 
332
    }
 
333
 
 
334
    // remove the contact from any relationships it was in.
 
335
    QContact thisContact = d->m_contacts.at(index);
 
336
    QList<QContactRelationship> allRelationships = relationships(QString(), thisContact, QContactRelationship::Either, error);
 
337
    if (*error != QContactManager::NoError && *error != QContactManager::DoesNotExistError) {
 
338
        *error = QContactManager::UnspecifiedError; // failed to clean up relationships
 
339
        return false;
 
340
    }
 
341
 
 
342
    // this is meant to be a transaction, so if any of these fail, we're in BIG TROUBLE.
 
343
    // a real backend will use DBMS transactions to ensure database integrity.
 
344
    removeRelationships(allRelationships, 0, error);
 
345
 
 
346
#if 0
 
347
    // having cleaned up the relationships, remove the contact from the lists.
 
348
    d->m_contacts.removeAt(index);
 
349
    d->m_contactIds.removeAt(index);
 
350
#else
 
351
    QContact &c = d->m_contacts[index];
 
352
    QContactExtendedDetail removedAt;
 
353
    foreach(QContactExtendedDetail d, c.details<QContactExtendedDetail>()) {
 
354
        if (d.name() == X_DELETED_AT) {
 
355
            removedAt = d;
 
356
            break;
 
357
        }
 
358
    }
 
359
    if (removedAt.isEmpty()) {
 
360
        removedAt.setName(X_DELETED_AT);
 
361
    }
 
362
    removedAt.setData(currentDateTime());
 
363
    c.saveDetail(&removedAt);
 
364
#endif
 
365
 
 
366
    *error = QContactManager::NoError;
 
367
 
 
368
    // and if it was the self contact, reset the self contact id
 
369
    if (contactId == d->m_selfContactId) {
 
370
        d->m_selfContactId = QContactId();
 
371
        changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(contactId, QContactId()));
 
372
    }
 
373
 
 
374
    changeSet.insertRemovedContact(contactId);
 
375
    return true;
 
376
}
 
377
 
 
378
/*! \reimp */
 
379
bool QContactMemoryEngine::removeContacts(const QList<QContactId> &contactIds, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
 
380
{
 
381
    if (contactIds.count() == 0) {
 
382
        *error = QContactManager::BadArgumentError;
 
383
        return false;
 
384
    }
 
385
 
 
386
    QContactChangeSet changeSet;
 
387
    QContactId current;
 
388
    QContactManager::Error operationError = QContactManager::NoError;
 
389
    for (int i = 0; i < contactIds.count(); i++) {
 
390
        current = contactIds.at(i);
 
391
        if (!removeContact(current, changeSet, error)) {
 
392
            operationError = *error;
 
393
            if (errorMap)
 
394
                errorMap->insert(i, operationError);
 
395
        }
 
396
    }
 
397
 
 
398
    *error = operationError;
 
399
    d->emitSharedSignals(&changeSet);
 
400
    // return false if some errors occurred
 
401
    return (*error == QContactManager::NoError);
 
402
}
 
403
 
 
404
/*! \reimp */
 
405
QList<QContactRelationship> QContactMemoryEngine::relationships(const QString &relationshipType, const QContact &participant, QContactRelationship::Role role, QContactManager::Error *error) const
 
406
{
 
407
    QContact defaultContact;
 
408
    QList<QContactRelationship> retn;
 
409
    for (int i = 0; i < d->m_relationships.size(); i++) {
 
410
        QContactRelationship curr = d->m_relationships.at(i);
 
411
 
 
412
        // check that the relationship type matches
 
413
        if (curr.relationshipType() != relationshipType && !relationshipType.isEmpty())
 
414
            continue;
 
415
 
 
416
        // if the participantId argument is default constructed, then the relationship matches.
 
417
        if (participant == defaultContact) {
 
418
            retn.append(curr);
 
419
            continue;
 
420
        }
 
421
 
 
422
        // otherwise, check that the participant exists and plays the required role in the relationship.
 
423
        if (role == QContactRelationship::First && curr.first() == participant) {
 
424
            retn.append(curr);
 
425
        } else if (role == QContactRelationship::Second && curr.second() == participant) {
 
426
            retn.append(curr);
 
427
        } else if (role == QContactRelationship::Either && (curr.first() == participant || curr.second() == participant)) {
 
428
            retn.append(curr);
 
429
        }
 
430
    }
 
431
 
 
432
    *error = QContactManager::NoError;
 
433
    if (retn.isEmpty())
 
434
        *error = QContactManager::DoesNotExistError;
 
435
    return retn;
 
436
}
 
437
 
 
438
/*! Saves the given relationship \a relationship, storing any error to \a error and
 
439
    filling the \a changeSet with ids of changed contacts and relationships as required
 
440
    Returns true if the operation was successful otherwise false.
 
441
*/
 
442
bool QContactMemoryEngine::saveRelationship(QContactRelationship *relationship, QContactChangeSet &changeSet, QContactManager::Error *error)
 
443
{
 
444
    // Attempt to validate the relationship.
 
445
    // first, check that the source contact exists and is in this manager.
 
446
    QString myUri = managerUri();
 
447
    int firstContactIndex = d->m_contactIds.indexOf(relationship->first().id());
 
448
    if ((!relationship->first().id().managerUri().isEmpty() && relationship->first().id().managerUri() != myUri)
 
449
            ||firstContactIndex == -1) {
 
450
        *error = QContactManager::InvalidRelationshipError;
 
451
        return false;
 
452
    }
 
453
 
 
454
    // second, check that the second contact exists (if it's local); we cannot check other managers' contacts.
 
455
    QContact dest = relationship->second();
 
456
    int secondContactIndex = d->m_contactIds.indexOf(dest.id());
 
457
 
 
458
    if (dest.id().managerUri().isEmpty() || dest.id().managerUri() == myUri) {
 
459
        // this entry in the destination list is supposedly stored in this manager.
 
460
        // check that it exists, and that it isn't the source contact (circular)
 
461
        if (secondContactIndex == -1 || dest.id() == relationship->first().id()) {
 
462
            *error = QContactManager::InvalidRelationshipError;
 
463
            return false;
 
464
        }
 
465
    }
 
466
 
 
467
    // the relationship is valid.  We need to update the manager URIs in the second contact if it is empty to our URI.
 
468
    if (dest.id().managerUri().isEmpty()) {
 
469
        // need to update the URI
 
470
        relationship->setSecond(dest);
 
471
    }
 
472
 
 
473
    // check to see if the relationship already exists in the database.  If so, replace.
 
474
    // We do this because we don't want duplicates in our lists / maps of relationships.
 
475
    *error = QContactManager::NoError;
 
476
    QList<QContactRelationship> allRelationships = d->m_relationships;
 
477
    for (int i = 0; i < allRelationships.size(); i++) {
 
478
        QContactRelationship curr = allRelationships.at(i);
 
479
        if (curr == *relationship) {
 
480
            return true;
 
481
            // TODO: set error to AlreadyExistsError and return false?
 
482
        }
 
483
    }
 
484
 
 
485
    // no matching relationship; must be new.  append it to lists in our map of relationships where required.
 
486
    QList<QContactRelationship> firstRelationships = d->m_orderedRelationships.value(relationship->first().id());
 
487
    QList<QContactRelationship> secondRelationships = d->m_orderedRelationships.value(relationship->second().id());
 
488
    firstRelationships.append(*relationship);
 
489
    secondRelationships.append(*relationship);
 
490
    d->m_orderedRelationships.insert(relationship->first().id(), firstRelationships);
 
491
    d->m_orderedRelationships.insert(relationship->second().id(), secondRelationships);
 
492
    changeSet.insertAddedRelationshipsContact(relationship->first().id());
 
493
    changeSet.insertAddedRelationshipsContact(relationship->second().id());
 
494
 
 
495
    // update the contacts involved
 
496
    QContactManagerEngine::setContactRelationships(&d->m_contacts[firstContactIndex], firstRelationships);
 
497
    QContactManagerEngine::setContactRelationships(&d->m_contacts[secondContactIndex], secondRelationships);
 
498
 
 
499
    // finally, insert into our list of all relationships, and return.
 
500
    d->m_relationships.append(*relationship);
 
501
    return true;
 
502
}
 
503
 
 
504
/*! \reimp */
 
505
bool QContactMemoryEngine::saveRelationships(QList<QContactRelationship> *relationships, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
 
506
{
 
507
    *error = QContactManager::NoError;
 
508
    QContactManager::Error functionError;
 
509
    QContactChangeSet changeSet;
 
510
 
 
511
    for (int i = 0; i < relationships->size(); i++) {
 
512
        QContactRelationship curr = relationships->at(i);
 
513
        saveRelationship(&curr, changeSet, &functionError);
 
514
        if (functionError != QContactManager::NoError && errorMap)
 
515
            errorMap->insert(i, functionError);
 
516
 
 
517
        // and replace the current relationship with the updated version.
 
518
        relationships->replace(i, curr);
 
519
 
 
520
        // also, update the total error if it did not succeed.
 
521
        if (functionError != QContactManager::NoError)
 
522
            *error = functionError;
 
523
    }
 
524
 
 
525
    d->emitSharedSignals(&changeSet);
 
526
    return (*error == QContactManager::NoError);
 
527
}
 
528
 
 
529
/*! Removes the given relationship \a relationship, storing any error to \a error and
 
530
    filling the \a changeSet with ids of changed contacts and relationships as required
 
531
    Returns true if the operation was successful otherwise false.
 
532
*/
 
533
bool QContactMemoryEngine::removeRelationship(const QContactRelationship &relationship, QContactChangeSet &changeSet, QContactManager::Error *error)
 
534
{
 
535
    // attempt to remove it from our list of relationships.
 
536
    if (!d->m_relationships.removeOne(relationship)) {
 
537
        *error = QContactManager::DoesNotExistError;
 
538
        return false;
 
539
    }
 
540
 
 
541
    // if that worked, then we need to remove it from the two locations in our map, also.
 
542
    QList<QContactRelationship> firstRelationships = d->m_orderedRelationships.value(relationship.first().id());
 
543
    QList<QContactRelationship> secondRelationships = d->m_orderedRelationships.value(relationship.second().id());
 
544
    firstRelationships.removeOne(relationship);
 
545
    secondRelationships.removeOne(relationship);
 
546
    d->m_orderedRelationships.insert(relationship.first().id(), firstRelationships);
 
547
    d->m_orderedRelationships.insert(relationship.second().id(), secondRelationships);
 
548
 
 
549
    // Update the contacts as well
 
550
    int firstContactIndex = d->m_contactIds.indexOf(relationship.first().id());
 
551
    int secondContactIndex = relationship.second().id().managerUri() == managerUri() ? d->m_contactIds.indexOf(relationship.second().id()) : -1;
 
552
    if (firstContactIndex != -1)
 
553
        QContactMemoryEngine::setContactRelationships(&d->m_contacts[firstContactIndex], firstRelationships);
 
554
    if (secondContactIndex != -1)
 
555
        QContactMemoryEngine::setContactRelationships(&d->m_contacts[secondContactIndex], secondRelationships);
 
556
 
 
557
    // set our changes, and return.
 
558
    changeSet.insertRemovedRelationshipsContact(relationship.first().id());
 
559
    changeSet.insertRemovedRelationshipsContact(relationship.second().id());
 
560
    *error = QContactManager::NoError;
 
561
    return true;
 
562
}
 
563
 
 
564
/*! \reimp */
 
565
bool QContactMemoryEngine::removeRelationships(const QList<QContactRelationship> &relationships, QMap<int, QContactManager::Error> *errorMap, QContactManager::Error *error)
 
566
{
 
567
    QContactManager::Error functionError;
 
568
    QContactChangeSet cs;
 
569
    for (int i = 0; i < relationships.size(); i++) {
 
570
        removeRelationship(relationships.at(i), cs, &functionError);
 
571
 
 
572
        // update the total error if it did not succeed.
 
573
        if (functionError != QContactManager::NoError) {
 
574
            if (errorMap)
 
575
                errorMap->insert(i, functionError);
 
576
            *error = functionError;
 
577
        }
 
578
    }
 
579
 
 
580
    d->emitSharedSignals(&cs);
 
581
    return (*error == QContactManager::NoError);
 
582
}
 
583
 
 
584
/*! \reimp */
 
585
void QContactMemoryEngine::requestDestroyed(QContactAbstractRequest *req)
 
586
{
 
587
    Q_UNUSED(req);
 
588
}
 
589
 
 
590
/*! \reimp */
 
591
bool QContactMemoryEngine::startRequest(QContactAbstractRequest *req)
 
592
{
 
593
    updateRequestState(req, QContactAbstractRequest::ActiveState);
 
594
    performAsynchronousOperation(req);
 
595
 
 
596
    return true;
 
597
}
 
598
 
 
599
bool QContactMemoryEngine::cancelRequest(QContactAbstractRequest *req)
 
600
{
 
601
    Q_UNUSED(req); // we can't cancel since we complete immediately
 
602
    return false;
 
603
}
 
604
 
 
605
/*! \reimp */
 
606
bool QContactMemoryEngine::waitForRequestFinished(QContactAbstractRequest *req, int msecs)
 
607
{
 
608
    // in our implementation, we always complete any operation we start.
 
609
    Q_UNUSED(msecs);
 
610
    Q_UNUSED(req);
 
611
 
 
612
    return true;
 
613
}
 
614
 
 
615
/*!
 
616
 * This slot is called some time after an asynchronous request is started.
 
617
 * It performs the required operation, sets the result and returns.
 
618
 */
 
619
void QContactMemoryEngine::performAsynchronousOperation(QContactAbstractRequest *currentRequest)
 
620
{
 
621
    // store up changes, and emit signals once at the end of the (possibly batch) operation.
 
622
    QContactChangeSet changeSet;
 
623
 
 
624
    // Now perform the active request and emit required signals.
 
625
    Q_ASSERT(currentRequest->state() == QContactAbstractRequest::ActiveState);
 
626
    switch (currentRequest->type()) {
 
627
        case QContactAbstractRequest::ContactFetchRequest:
 
628
        {
 
629
            QContactFetchRequest *r = static_cast<QContactFetchRequest*>(currentRequest);
 
630
            QContactFilter filter = r->filter();
 
631
            QList<QContactSortOrder> sorting = r->sorting();
 
632
            QContactFetchHint fetchHint = r->fetchHint();
 
633
 
 
634
            QContactManager::Error operationError = QContactManager::NoError;
 
635
            QList<QContact> requestedContacts = contacts(filter, sorting, fetchHint, &operationError);
 
636
 
 
637
            // update the request with the results.
 
638
            if (!requestedContacts.isEmpty() || operationError != QContactManager::NoError)
 
639
                updateContactFetchRequest(r, requestedContacts, operationError, QContactAbstractRequest::FinishedState);
 
640
            else
 
641
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
642
        }
 
643
        break;
 
644
 
 
645
        case QContactAbstractRequest::ContactFetchByIdRequest:
 
646
        {
 
647
            QContactFetchByIdRequest *r = static_cast<QContactFetchByIdRequest*>(currentRequest);
 
648
            QContactIdFilter idFilter;
 
649
            idFilter.setIds(r->contactIds());
 
650
            QList<QContactSortOrder> sorting;
 
651
            QContactFetchHint fetchHint = r->fetchHint();
 
652
            QContactManager::Error error = QContactManager::NoError;
 
653
            QList<QContact> requestedContacts = contacts(idFilter, sorting, fetchHint, &error);
 
654
            // Build an index into the results
 
655
            QHash<QContactId, int> idMap; // value is index into unsorted
 
656
            if (error == QContactManager::NoError) {
 
657
                for (int i = 0; i < requestedContacts.size(); i++) {
 
658
                    idMap.insert(requestedContacts[i].id(), i);
 
659
                }
 
660
            }
 
661
            // Find the order in which the results should be presented
 
662
            // Build up the results and errors
 
663
            QList<QContact> results;
 
664
            QMap<int, QContactManager::Error> errorMap;
 
665
            int index = 0;
 
666
            foreach (const QContactId &id, r->contactIds()) {
 
667
                if (!idMap.contains(id)) {
 
668
                    errorMap.insert(index, QContactManager::DoesNotExistError);
 
669
                    error = QContactManager::DoesNotExistError;
 
670
                    results.append(QContact());
 
671
                } else {
 
672
                    results.append(requestedContacts[idMap[id]]);
 
673
                }
 
674
                index++;
 
675
            }
 
676
 
 
677
            // update the request with the results.
 
678
            if (!requestedContacts.isEmpty() || error != QContactManager::NoError)
 
679
                QContactManagerEngine::updateContactFetchByIdRequest(r, results, error, errorMap, QContactAbstractRequest::FinishedState);
 
680
            else
 
681
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
682
        }
 
683
        break;
 
684
 
 
685
        case QContactAbstractRequest::ContactIdFetchRequest:
 
686
        {
 
687
            QContactIdFetchRequest *r = static_cast<QContactIdFetchRequest*>(currentRequest);
 
688
            QContactFilter filter = r->filter();
 
689
            QList<QContactSortOrder> sorting = r->sorting();
 
690
 
 
691
            QContactManager::Error operationError = QContactManager::NoError;
 
692
            QList<QContactId> requestedContactIds = contactIds(filter, sorting, &operationError);
 
693
 
 
694
            if (!requestedContactIds.isEmpty() || operationError != QContactManager::NoError)
 
695
                updateContactIdFetchRequest(r, requestedContactIds, operationError, QContactAbstractRequest::FinishedState);
 
696
            else
 
697
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
698
        }
 
699
        break;
 
700
 
 
701
        case QContactAbstractRequest::ContactSaveRequest:
 
702
        {
 
703
            QContactSaveRequest *r = static_cast<QContactSaveRequest*>(currentRequest);
 
704
            QList<QContact> contacts = r->contacts();
 
705
 
 
706
            QContactManager::Error operationError = QContactManager::NoError;
 
707
            QMap<int, QContactManager::Error> errorMap;
 
708
            saveContacts(&contacts, &errorMap, &operationError, r->typeMask());
 
709
 
 
710
            updateContactSaveRequest(r, contacts, operationError, errorMap, QContactAbstractRequest::FinishedState);
 
711
        }
 
712
        break;
 
713
 
 
714
        case QContactAbstractRequest::ContactRemoveRequest:
 
715
        {
 
716
            // this implementation provides scant information to the user
 
717
            // the operation either succeeds (all contacts matching the filter were removed)
 
718
            // or it fails (one or more contacts matching the filter could not be removed)
 
719
            // if a failure occurred, the request error will be set to the most recent
 
720
            // error that occurred during the remove operation.
 
721
            QContactRemoveRequest *r = static_cast<QContactRemoveRequest*>(currentRequest);
 
722
            QContactManager::Error operationError = QContactManager::NoError;
 
723
            QList<QContactId> contactsToRemove = r->contactIds();
 
724
            QMap<int, QContactManager::Error> errorMap;
 
725
 
 
726
            for (int i = 0; i < contactsToRemove.size(); i++) {
 
727
                QContactManager::Error tempError;
 
728
                removeContact(contactsToRemove.at(i), changeSet, &tempError);
 
729
 
 
730
                if (tempError != QContactManager::NoError) {
 
731
                    errorMap.insert(i, tempError);
 
732
                    operationError = tempError;
 
733
                }
 
734
            }
 
735
 
 
736
            if (!errorMap.isEmpty() || operationError != QContactManager::NoError)
 
737
                updateContactRemoveRequest(r, operationError, errorMap, QContactAbstractRequest::FinishedState);
 
738
            else
 
739
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
740
        }
 
741
        break;
 
742
 
 
743
        case QContactAbstractRequest::RelationshipFetchRequest:
 
744
        {
 
745
            QContactRelationshipFetchRequest *r = static_cast<QContactRelationshipFetchRequest*>(currentRequest);
 
746
            QContactManager::Error operationError = QContactManager::NoError;
 
747
            QList<QContactManager::Error> operationErrors;
 
748
            QList<QContactRelationship> allRelationships = relationships(QString(), QContact(), QContactRelationship::Either, &operationError);
 
749
            QList<QContactRelationship> requestedRelationships;
 
750
 
 
751
            // select the requested relationships.
 
752
            for (int i = 0; i < allRelationships.size(); i++) {
 
753
                QContactRelationship currRel = allRelationships.at(i);
 
754
                if (r->first() != QContact() && r->first() != currRel.first())
 
755
                    continue;
 
756
                if (r->second() != QContact() && r->second() != currRel.second())
 
757
                    continue;
 
758
                if (!r->relationshipType().isEmpty() && r->relationshipType() != currRel.relationshipType())
 
759
                    continue;
 
760
                requestedRelationships.append(currRel);
 
761
            }
 
762
 
 
763
            // update the request with the results.
 
764
            if (!requestedRelationships.isEmpty() || operationError != QContactManager::NoError)
 
765
                updateRelationshipFetchRequest(r, requestedRelationships, operationError, QContactAbstractRequest::FinishedState);
 
766
            else
 
767
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
768
        }
 
769
        break;
 
770
 
 
771
        case QContactAbstractRequest::RelationshipRemoveRequest:
 
772
        {
 
773
            QContactRelationshipRemoveRequest *r = static_cast<QContactRelationshipRemoveRequest*>(currentRequest);
 
774
            QContactManager::Error operationError = QContactManager::NoError;
 
775
            QList<QContactRelationship> relationshipsToRemove = r->relationships();
 
776
            QMap<int, QContactManager::Error> errorMap;
 
777
 
 
778
            removeRelationships(r->relationships(), &errorMap, &operationError);
 
779
 
 
780
            if (!errorMap.isEmpty() || operationError != QContactManager::NoError)
 
781
                updateRelationshipRemoveRequest(r, operationError, errorMap, QContactAbstractRequest::FinishedState);
 
782
            else
 
783
                updateRequestState(currentRequest, QContactAbstractRequest::FinishedState);
 
784
        }
 
785
        break;
 
786
 
 
787
        case QContactAbstractRequest::RelationshipSaveRequest:
 
788
        {
 
789
            QContactRelationshipSaveRequest *r = static_cast<QContactRelationshipSaveRequest*>(currentRequest);
 
790
            QContactManager::Error operationError = QContactManager::NoError;
 
791
            QMap<int, QContactManager::Error> errorMap;
 
792
            QList<QContactRelationship> requestRelationships = r->relationships();
 
793
 
 
794
            saveRelationships(&requestRelationships, &errorMap, &operationError);
 
795
 
 
796
            // update the request with the results.
 
797
            updateRelationshipSaveRequest(r, requestRelationships, operationError, errorMap, QContactAbstractRequest::FinishedState);
 
798
        }
 
799
        break;
 
800
 
 
801
        default: // unknown request type.
 
802
        break;
 
803
    }
 
804
 
 
805
    // now emit any signals we have to emit
 
806
    d->emitSharedSignals(&changeSet);
 
807
}
 
808
 
 
809
QDateTime QContactMemoryEngine::deleted(const QContact &c) const
 
810
{
 
811
    foreach(const QContactExtendedDetail &xd, c.details<QContactExtendedDetail>()) {
 
812
        if (xd.name() == X_DELETED_AT) {
 
813
            return xd.data().toDateTime();
 
814
        }
 
815
    }
 
816
    return QDateTime();
 
817
}
 
818
 
 
819
QDateTime QContactMemoryEngine::currentDateTime() const
 
820
{
 
821
    QDateTime dateTime = property("CURRENT_DATE_TIME").toDateTime();
 
822
    if (dateTime.isValid()) {
 
823
        return dateTime;
 
824
    } else {
 
825
        return QDateTime::currentDateTime();
 
826
    }
 
827
}
 
828
 
 
829
void QContactMemoryEngine::partiallySyncDetails(QContact *to, const QContact &from, const QList<QContactDetail::DetailType> &mask)
 
830
{
 
831
    // these details in old contact
 
832
    QList<QContactDetail> fromDetails;
 
833
    // these details in new contact
 
834
    QList<QContactDetail> toDetails;
 
835
    // Collect details that match mask
 
836
    foreach (QContactDetail::DetailType type, mask) {
 
837
        fromDetails.append(from.details(type));
 
838
        toDetails.append(to->details(type));
 
839
    }
 
840
    // check details to remove
 
841
    foreach (QContactDetail detail, toDetails) {
 
842
        if (!fromDetails.contains(detail))
 
843
            to->removeDetail(&detail);
 
844
    }
 
845
    // check details to save
 
846
    foreach (QContactDetail detail, fromDetails) {
 
847
        if (!toDetails.contains(detail))
 
848
            to->saveDetail(&detail);
 
849
    }
 
850
}
 
851
 
 
852
/*!
 
853
 * \reimp
 
854
 */
 
855
bool QContactMemoryEngine::isRelationshipTypeSupported(const QString& relationshipType, QContactType::TypeValues contactType) const
 
856
{
 
857
    // the memory backend supports arbitrary relationship types
 
858
    // but some relationship types don't make sense for groups.
 
859
    if (contactType == QContactType::TypeGroup) {
 
860
        if (relationshipType == QContactRelationship::HasSpouse() || relationshipType == QContactRelationship::HasAssistant()) {
 
861
            return false;
 
862
        }
 
863
    }
 
864
 
 
865
    // all other relationship types for all contact types are supported.
 
866
    return true;
 
867
}
 
868
 
 
869
/*!
 
870
 * \reimp
 
871
 */
 
872
QList<QVariant::Type> QContactMemoryEngine::supportedDataTypes() const
 
873
{
 
874
    QList<QVariant::Type> st;
 
875
    st.append(QVariant::String);
 
876
    st.append(QVariant::Date);
 
877
    st.append(QVariant::DateTime);
 
878
    st.append(QVariant::Time);
 
879
    st.append(QVariant::Bool);
 
880
    st.append(QVariant::Char);
 
881
    st.append(QVariant::Int);
 
882
    st.append(QVariant::UInt);
 
883
    st.append(QVariant::LongLong);
 
884
    st.append(QVariant::ULongLong);
 
885
    st.append(QVariant::Double);
 
886
 
 
887
    return st;
 
888
}
 
889
 
 
890
/*!
 
891
 * The function returns true if the backend natively supports the given filter \a filter, otherwise false.
 
892
 */
 
893
bool QContactMemoryEngine::isFilterSupported(const QContactFilter &filter) const
 
894
{
 
895
    Q_UNUSED(filter);
 
896
    // Until we add hashes for common stuff, fall back to slow code
 
897
    return false;
 
898
}
 
899
 
 
900
bool QContactMemoryEngine::saveContacts(QList<QContact> *contacts, QMap<int, QContactManager::Error> *errorMap,
 
901
                                        QContactManager::Error *error, const QList<QContactDetail::DetailType> &mask)
 
902
{
 
903
    if (!contacts) {
 
904
        *error = QContactManager::BadArgumentError;
 
905
        return false;
 
906
    }
 
907
 
 
908
    QContactChangeSet changeSet;
 
909
    QContact current;
 
910
    QContactManager::Error operationError = QContactManager::NoError;
 
911
    for (int i = 0; i < contacts->count(); i++) {
 
912
        current = contacts->at(i);
 
913
        if (!saveContact(&current, changeSet, error, mask)) {
 
914
            operationError = *error;
 
915
            if (errorMap)
 
916
                errorMap->insert(i, operationError);
 
917
        } else {
 
918
            (*contacts)[i] = current;
 
919
        }
 
920
    }
 
921
 
 
922
    *error = operationError;
 
923
    d->emitSharedSignals(&changeSet);
 
924
    // return false if some error occurred
 
925
    return (*error == QContactManager::NoError);
 
926
}
 
927
 
 
928
bool QContactMemoryEngine::saveContact(QContact *theContact, QContactChangeSet &changeSet,
 
929
                                       QContactManager::Error *error, const QList<QContactDetail::DetailType> &mask)
 
930
{
 
931
    // ensure that the contact's details conform to their definitions
 
932
    if (!validateContact(*theContact, error)) {
 
933
        return false;
 
934
    }
 
935
 
 
936
    QContactId id(theContact->id());
 
937
    if (!id.managerUri().isEmpty() && id.managerUri() != managerUri()) {
 
938
        // the contact doesn't belong to this manager
 
939
        *error = QContactManager::DoesNotExistError;
 
940
        return false;
 
941
    }
 
942
 
 
943
    // check to see if this contact already exists
 
944
    int index = d->m_contactIds.indexOf(id);
 
945
    if (index != -1) {
 
946
        /* We also need to check that there are no modified create only details */
 
947
        QContact oldContact = d->m_contacts.at(index);
 
948
 
 
949
        if (oldContact.type() != theContact->type()) {
 
950
            *error = QContactManager::AlreadyExistsError;
 
951
            return false;
 
952
        }
 
953
 
 
954
        // check if this is partial save
 
955
        if (!mask.isEmpty()) {
 
956
            QContact tempContact = oldContact;
 
957
            partiallySyncDetails(&tempContact, *theContact, mask);
 
958
            *theContact = tempContact;
 
959
        }
 
960
 
 
961
//        Keep the value from contact
 
962
//        ===========================
 
963
//        QContactTimestamp ts = theContact->detail(QContactTimestamp::Type);
 
964
//        ts.setLastModified(QDateTime::currentDateTime());
 
965
//        QContactManagerEngine::setDetailAccessConstraints(&ts, QContactDetail::ReadOnly | QContactDetail::Irremovable);
 
966
//        theContact->saveDetail(&ts);
 
967
 
 
968
        // Looks ok, so continue
 
969
        d->m_contacts.replace(index, *theContact);
 
970
        changeSet.insertChangedContact(theContact->id());
 
971
    } else {
 
972
        // id does not exist; if not zero, fail.
 
973
        QContactId newId;
 
974
        if (theContact->id() != QContactId() && theContact->id() != newId) {
 
975
            // the ID is not empty, and it doesn't identify an existing contact in our database either.
 
976
            *error = QContactManager::DoesNotExistError;
 
977
            return false;
 
978
        }
 
979
 
 
980
        // check if this is partial save
 
981
        if (!mask.isEmpty()) {
 
982
            QContact tempContact;
 
983
            partiallySyncDetails(&tempContact, *theContact, mask);
 
984
            *theContact = tempContact;
 
985
        }
 
986
 
 
987
        /* New contact */
 
988
//        Keep the value from contact
 
989
//        ===========================
 
990
//        QContactTimestamp ts = theContact->detail(QContactTimestamp::Type);
 
991
//        ts.setLastModified(QDateTime::currentDateTime());
 
992
//        ts.setCreated(ts.lastModified());
 
993
//        setDetailAccessConstraints(&ts, QContactDetail::ReadOnly | QContactDetail::Irremovable);
 
994
//        theContact->saveDetail(&ts);
 
995
 
 
996
        // update the contact item - set its ID
 
997
        quint32 nextContactId = d->m_nextContactId; // don't increment the persistent version until we're successful or we know it collides.
 
998
        nextContactId += 1; // but do increment the temporary version to check for collision
 
999
        QContactMemoryEngineId *newMemoryEngineId = new QContactMemoryEngineId;
 
1000
        newMemoryEngineId->m_contactId = nextContactId;
 
1001
        newMemoryEngineId->m_managerUri = d->m_managerUri;
 
1002
        QContactId newContactId = QContactId(newMemoryEngineId);
 
1003
        theContact->setId(newContactId);
 
1004
 
 
1005
        // note: do NOT delete the QContactMemoryEngineId -- the QContactId ctor takes ownership of it.
 
1006
 
 
1007
 
 
1008
        // finally, add the contact to our internal lists and return
 
1009
        d->m_contacts.append(*theContact);                   // add contact to list
 
1010
        d->m_contactIds.append(theContact->id());  // track the contact id.
 
1011
 
 
1012
        changeSet.insertAddedContact(theContact->id());
 
1013
        // successful, now increment the persistent version of the next item id.
 
1014
        d->m_nextContactId += 1;
 
1015
    }
 
1016
 
 
1017
    *error = QContactManager::NoError;     // successful.
 
1018
    return true;
 
1019
}
 
1020
 
 
1021
/*!
 
1022
  \class QContactMemoryEngineId
 
1023
  \brief The QContactMemoryEngineId class provides an id which uniquely identifies
 
1024
  a QContact stored within a QContactMemoryEngine.
 
1025
 
 
1026
  \internal
 
1027
  It may be used as a reference implementation, although since different platforms
 
1028
  have different semantics for ids
 
1029
  the precise implementation required may differ.
 
1030
 */
 
1031
QContactMemoryEngineId::QContactMemoryEngineId()
 
1032
    : QContactEngineId(), m_contactId(0)
 
1033
{
 
1034
}
 
1035
 
 
1036
QContactMemoryEngineId::QContactMemoryEngineId(quint32 contactId, const QString &managerUri)
 
1037
    : QContactEngineId(), m_contactId(contactId), m_managerUri(managerUri)
 
1038
{
 
1039
}
 
1040
 
 
1041
QContactMemoryEngineId::~QContactMemoryEngineId()
 
1042
{
 
1043
}
 
1044
 
 
1045
QContactMemoryEngineId::QContactMemoryEngineId(const QContactMemoryEngineId &other)
 
1046
    : QContactEngineId(), m_contactId(other.m_contactId), m_managerUri(other.m_managerUri)
 
1047
{
 
1048
}
 
1049
 
 
1050
QContactMemoryEngineId::QContactMemoryEngineId(const QMap<QString, QString> &parameters, const QString &engineIdString)
 
1051
    : QContactEngineId()
 
1052
{
 
1053
    m_contactId = engineIdString.toInt();
 
1054
    m_managerUri = QContactManager::buildUri(ENGINE_NAME, parameters);
 
1055
}
 
1056
 
 
1057
bool QContactMemoryEngineId::isEqualTo(const QContactEngineId *other) const
 
1058
{
 
1059
    if (m_contactId != static_cast<const QContactMemoryEngineId*>(other)->m_contactId)
 
1060
        return false;
 
1061
    return true;
 
1062
}
 
1063
 
 
1064
bool QContactMemoryEngineId::isLessThan(const QContactEngineId *other) const
 
1065
{
 
1066
    const QContactMemoryEngineId *otherPtr = static_cast<const QContactMemoryEngineId*>(other);
 
1067
    if (m_managerUri < otherPtr->m_managerUri)
 
1068
        return true;
 
1069
    if (m_contactId < otherPtr->m_contactId)
 
1070
        return true;
 
1071
    return false;
 
1072
}
 
1073
 
 
1074
QString QContactMemoryEngineId::managerUri() const
 
1075
{
 
1076
    return m_managerUri;
 
1077
}
 
1078
 
 
1079
QString QContactMemoryEngineId::toString() const
 
1080
{
 
1081
    return QString::number(m_contactId);
 
1082
}
 
1083
 
 
1084
QContactEngineId* QContactMemoryEngineId::clone() const
 
1085
{
 
1086
    return new QContactMemoryEngineId(m_contactId, m_managerUri);
 
1087
}
 
1088
 
 
1089
#ifndef QT_NO_DEBUG_STREAM
 
1090
QDebug& QContactMemoryEngineId::debugStreamOut(QDebug &dbg) const
 
1091
{
 
1092
    dbg.nospace() << "QContactMemoryEngineId(" << m_managerUri << "," << m_contactId << ")";
 
1093
    return dbg.maybeSpace();
 
1094
}
 
1095
#endif
 
1096
 
 
1097
uint QContactMemoryEngineId::hash() const
 
1098
{
 
1099
    return m_contactId;
 
1100
}
 
1101
 
 
1102
#include "moc_qcontactmemorybackend_p.cpp"
 
1103
 
 
1104
QT_END_NAMESPACE_CONTACTS