Changes: Use QString instead of QUrl for Iris
[qtcontacts-tracker:qtcontacts-tracker.git] / src / engine / contactunmergerequest.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt Mobility Components.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "contactunmergerequest.h"
43
44 #include <dao/sparqlresolver.h>
45 #include <dao/subject.h>
46 #include <dao/support.h>
47 #include <engine/engine.h>
48 #include <lib/customdetails.h>
49 #include <lib/unmergeimcontactsrequest.h>
50
51 #include <QtSparql>
52
53 QTrackerContactSaveOrUnmergeRequest::QTrackerContactSaveOrUnmergeRequest(QContactAbstractRequest *request,
54                                                                          QContactTrackerEngine *engine,
55                                                                          QObject *parent)
56     : QTrackerBaseRequest<QctUnmergeIMContactsRequest>(request, engine, parent)
57 {
58 }
59
60 QTrackerContactSaveOrUnmergeRequest::~QTrackerContactSaveOrUnmergeRequest()
61 {
62 }
63
64 QString
65 QTrackerContactSaveOrUnmergeRequest::buildQuery()
66 {
67     QStringList queries;
68     const QDateTime currentTime = QDateTime::currentDateTime();
69
70     foreach(const QContactOnlineAccount &account, m_request->unmergeOnlineAccounts()) {
71         const QString accountPath = account.value(QContactOnlineAccount__FieldAccountPath);
72         const QString accountUri = account.accountUri();
73
74         const QString telepathyIri = makeTelepathyIri(accountPath, accountUri);
75         const QString telepathyAffiliationIri = QLatin1String("affiliation:") +  telepathyIri;
76         const QString localContactIri = makeAnonymousIri(QUuid::createUuid());
77
78         // FIXME: Asked tracker guys about the problem with query:
79         //
80         // INSERT INTO </org/freedesktop/fake/account/555!555@ovi.com> {
81         //   <contact:1234> a nco:PersonContact; ?p ?v
82         // } WHERE {
83         //   <contact:555> ?p ?v.{ GRAPH </org/freedesktop/fake/account/555!555@ovi.com> { ?v a ?v1 } }
84         // }
85         //
86         // Generic query ?v a ?v1 doesnt work (whether it is in graph or not), so forced to
87         // hardcode unmerging, only to support IM address copying.
88         //
89         // Meanwhile - asking juergbi :)
90
91         static const QString queryTemplate = QLatin1String
92                 ( "INSERT {\n"
93                   "  GRAPH <%1> {\n"
94                   "    <%3> a nco:PersonContact;\n"
95                   "    nie:generator 'telepathy';\n"
96                   "    nie:contentLastModified \"%5\";\n"
97                   "    nco:hasAffiliation <%2>.\n"
98                   "    <%2> a nco:Affiliation.\n"
99                   "  }\n"
100                   "}\n"
101
102                   "INSERT { GRAPH <%1> { <%2> nco:hasIMAddress <%1> } }\n"
103                   "WHERE { ?s nco:hasAffiliation [ nco:hasIMAddress <%1> ]\n"
104                   "        FILTER(%4=tracker:id(?s)) }\n"
105
106                   // For case IMAddress is not under affiliation.
107                   // Happens as it is still possible to edit contactsd contacts.
108                   "INSERT { GRAPH <%1> { <%2> nco:hasIMAddress <%1> } }\n"
109                   "WHERE { ?s nco:hasIMAddress <%1> FILTER(%4=tracker:id(?s)) }\n"
110
111                   "DELETE { ?s nco:hasAffiliation <%2> }\n"
112                   "WHERE { ?s nco:hasAffiliation <%2> FILTER(%4=tracker:id(?s)) }\n"
113
114                   // Again, for case IMAddress is not under devoted affiliation.
115                   // Happens as it is still possible to edit contactsd contacts by qtcontacts tracker.
116                   "DELETE { ?s nco:hasIMAddress <%1> }\n"
117                   "WHERE { ?s nco:hasIMAddress <%1> FILTER(%4=tracker:id(?s)) }\n"
118
119                   "DELETE { ?v nco:hasIMAddress <%1> } "
120                   "WHERE { ?s nco:hasAffiliation ?v . ?v nco:hasIMAddress <%1> FILTER(%4=tracker:id(?s)) }\n"
121                 );
122
123         queries += queryTemplate.arg(telepathyIri, telepathyAffiliationIri, localContactIri,
124                                      QString::number(m_request->sourceContact().localId()),
125                                      currentTime.toString(Qt::ISODate));
126
127         m_unmergedContactIris += localContactIri;
128     }
129
130     return queries.join(QLatin1String("\n"));
131 }
132
133 bool
134 QTrackerContactSaveOrUnmergeRequest::start()
135 {
136     // We explicitly don't check for contacts existance (DoesNotExistError error)
137     // because checking for contact existance costs time.
138     return runQuery(QSparqlQuery(buildQuery(), QSparqlQuery::InsertStatement));
139 }
140
141 bool
142 QTrackerContactSaveOrUnmergeRequest::handleQuerySuccess(QSparqlResult */*result*/)
143 {
144     QScopedPointer<QctTrackerIdResolver> resolver(new QctTrackerIdResolver(m_unmergedContactIris));
145     connect(resolver.data(), SIGNAL(finished()), SLOT(onTrackerIdsResolved()));
146
147     if (not resolver->lookup()) {
148         reportError(QLatin1String("Cannot resolve tracker ids"));
149     } else {
150         resolver.take()->setParent(this);
151     }
152
153     // don't emit succes yet, success depends on the outcome of the ID resolver
154     // or reportError will already have done it
155     return false;
156 }
157
158 void
159 QTrackerContactSaveOrUnmergeRequest::onTrackerIdsResolved()
160 {
161     QctTrackerIdResolver *const resolver = qobject_cast<QctTrackerIdResolver *>(sender());
162
163     if (0 == resolver) {
164         qctWarn("Ignoring signal from invalid sender.");
165         return;
166     }
167
168     m_unmergedContactIds = resolver->trackerIds();
169     emitResult(QContactManager::NoError);
170 }
171
172 void
173 QTrackerContactSaveOrUnmergeRequest::emitResult(QContactManager::Error error)
174 {
175     m_request->setUnmergedContacts(m_unmergedContactIds);
176     engine()->updateContactSaveRequest(m_request, QList<QContact>(), error,
177                                        QMap<int, QContactManager::Error>(),
178                                        QContactAbstractRequest::FinishedState);
179 }
180
181
182 ///////////////////////////////////////////////////////////////////////////////////////////////////
183
184 #include "moc_contactunmergerequest.cpp"