Changes: Move ShowModels handling in common function
[qtcontacts-tracker:qtcontacts-tracker.git] / src / engine / abstractrequest.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 "abstractrequest.h"
43
44 #include <dao/ontologies/nco.h>
45 #include <dao/sparqlconnectionmanager.h>
46 #include <engine/engine.h>
47
48 #include <QtSparql>
49
50 ///////////////////////////////////////////////////////////////////////////////////////////////////
51
52 CUBI_USE_NAMESPACE
53 CUBI_USE_NAMESPACE_RESOURCES
54
55 ///////////////////////////////////////////////////////////////////////////////////////////////////
56
57 QTrackerAbstractRequest::QTrackerAbstractRequest(QContactTrackerEngine *engine, QObject *parent)
58     : QObject(parent)
59     , m_engine(engine)
60     , m_logger(makePrefix(engine))
61 {
62     if (0 == m_engine) {
63         qctFail("No engine passed to request worker");
64     }
65
66     m_logger.setShowLocation(::qctLogger().showLocation());
67 }
68
69 QTrackerAbstractRequest::~QTrackerAbstractRequest()
70 {
71 }
72
73 QString
74 QTrackerAbstractRequest::makePrefix(QContactTrackerEngine *engine)
75 {
76     QString prefix;
77
78     if (0 != engine) {
79         prefix = engine->managerUri();
80     }
81
82     // strip common URI prefix
83     static const QString commonPrefix = QLatin1String("qtcontacts:tracker:");
84
85     if (prefix.startsWith(commonPrefix)) {
86         prefix = prefix.mid(commonPrefix.length());
87     }
88
89     return prefix;
90 }
91
92 static QContactTrackerEngine::DebugFlag
93 queryDebugFlag(const QSparqlQuery &query)
94 {
95     switch(query.type()) {
96     case QSparqlQuery::InsertStatement:
97     case QSparqlQuery::DeleteStatement:
98         return QContactTrackerEngine::ShowUpdates;
99
100     default:
101         break;
102     }
103
104     return QContactTrackerEngine::ShowSelects;
105 }
106
107 bool
108 QTrackerAbstractRequest::runQuery(const QSparqlQuery &query, QSparqlResult **resultPtr)
109 {
110     if (engine()->hasDebugFlag(queryDebugFlag(query))) {
111         qDebug() << query.query();
112     }
113
114     QSparqlConnection &connection = QctSparqlConnectionManager::defaultConnection();
115
116     if (not connection.isValid()) {
117         reportError(QLatin1String("No valid QtSparql connection."));
118         return false;
119     }
120
121     QScopedPointer<QSparqlResult> result(connection.exec(query));
122
123     if (result->hasError()) {
124         reportError(result->lastError().message());
125         return false;
126     }
127
128     if (0 != qobject_cast<QSparqlConnection*>(result->parent())) {
129         // take ownership of the result if it has default owner
130         result->setParent(this);
131     }
132
133     if (resultPtr != 0) {
134         *resultPtr = result.data();
135     }
136
137     connect(result.take(), SIGNAL(finished()), SLOT(onSparqlQueryFinished()));
138
139     return true;
140 }
141
142 bool
143 QTrackerAbstractRequest::updateLocalIds(const QList<QUrl> &contactIris,
144                                         const QList<QContactLocalId> &localIds, const char *slot)
145 {
146     // Check if number of resolved tracker ids matches expectation.
147     if (contactIris.count() != localIds.count()) {
148         reportError(QLatin1String("Resolver provides invalid number of tracker ids"));
149         return false;
150     }
151
152     // Prepare query for updating nco:contactLocalUID
153     Insert localIdUpdate(engine()->graphIri());
154
155     // Apply local ids found by resolver.
156     for(int i = 0; i < contactIris.count(); ++i) {
157         if (0 != localIds[i]) {
158             localIdUpdate.addData(ResourceValue(contactIris[i]),
159                                   nco::contactLocalUID::resource(),
160                                   LiteralValue(localIds[i]));
161         }
162     }
163
164     // run query to store local ids
165     Options::SparqlOptions options = Options::DefaultSparqlOptions;
166
167     if (engine()->hasDebugFlag(QContactTrackerEngine::ShowUpdates)) {
168         options |= Options::PrettyPrint;
169     }
170
171     const QString queryString = localIdUpdate.sparql(options);
172
173     if (engine()->hasDebugFlag(QContactTrackerEngine::ShowUpdates)) {
174         qDebug() << queryString;
175     }
176
177     if (not runQuery(QSparqlQuery(queryString, QSparqlQuery::InsertStatement), slot)) {
178         reportError(QLatin1String("Cannot insert contact ids"));
179         return false;
180     }
181
182     return true;
183 }
184
185 void
186 QTrackerAbstractRequest::reportError(const QString &message, QContactManager::Error error)
187 {
188     qctWarn(QString::fromLatin1("%1 failed: %2").
189             arg(QLatin1String(metaObject()->className()),
190                 qctTruncate(message)));
191
192     emitResult(error);
193 }
194
195 void
196 QTrackerAbstractRequest::onSparqlQueryFinished()
197 {
198     QSparqlResult *const result = qobject_cast<QSparqlResult *>(sender());
199
200     if (0 == result) {
201         qctWarn("Ignoring signal from invalid sender.");
202         return;
203     }
204
205
206     if (result->hasError()) {
207         // reportError emits a signal which might cause deletion of the sender
208         const QSparqlError error = result->lastError();
209         result->deleteLater();
210
211         reportError(error.message(), handleQueryError(error));
212     } else {
213         if ((engine()->hasDebugFlag(QContactTrackerEngine::ShowModels)) &&
214                 (result->isTable())) {
215             for(bool hasRow = result->first(); hasRow; hasRow = result->next()) {
216                 qDebug() << result->current();
217             }
218
219             // rewind result
220             result->first();
221             result->previous();
222         }
223
224         QContactManager::Error error = QContactManager::NoError;
225         bool done = handleQuerySuccess(result, error);
226
227         if (result->parent() == this) {
228             // only dispose result already if we own the result
229             result->deleteLater();
230         }
231
232         if (done) {
233             emitResult(error);
234         }
235     }
236 }