~chris.gagnon/+junk/qtpim-coverage

« back to all changes in this revision

Viewing changes to src/plugins/organizer/jsondb/qorganizerjsondbconverter.cpp

  • Committer: chris.gagnon
  • Date: 2013-12-10 23:09:37 UTC
  • Revision ID: chris.gagnon@canonical.com-20131210230937-2akf1ft1edcttk87
first post

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 QtPIM 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 "qorganizerjsondbconverter.h"
 
43
#include "qorganizerjsondbid.h"
 
44
#include "qorganizerjsondbstring.h"
 
45
#include "qorganizerjsondbengine.h"
 
46
#include <QtOrganizer/qorganizermanagerengine.h>
 
47
#include <QtOrganizer/qorganizeritemfilters.h>
 
48
 
 
49
#include <QtCore/qjsonarray.h>
 
50
 
 
51
QT_BEGIN_NAMESPACE_ORGANIZER
 
52
 
 
53
const int QOrganizerJsonDbConverter::enumMapEnd(-1212);
 
54
 
 
55
const QMap<int, QString> QOrganizerJsonDbConverter::filterablePropertyNames()
 
56
{
 
57
    static QMap<int, QString> filterableProperties;
 
58
    if (filterableProperties.isEmpty()) {
 
59
        filterableProperties.insert(QOrganizerItemComment::FieldComment,
 
60
                                    QOrganizerJsonDbStr::itemComments());
 
61
        filterableProperties.insert(QOrganizerItemDescription::FieldDescription,
 
62
                                    QOrganizerJsonDbStr::itemDescription());
 
63
        filterableProperties.insert(QOrganizerItemDisplayLabel::FieldLabel,
 
64
                                    QOrganizerJsonDbStr::itemDisplayName());
 
65
        filterableProperties.insert(QOrganizerEventRsvp::FieldOrganizerEmail,
 
66
                                    QOrganizerJsonDbStr::eventRsvpOrganizerEmail());
 
67
        filterableProperties.insert(QOrganizerEventRsvp::FieldOrganizerName,
 
68
                                    QOrganizerJsonDbStr::eventRsvpOrganizerName());
 
69
        filterableProperties.insert(QOrganizerEventRsvp::FieldParticipationRole,
 
70
                                    QOrganizerJsonDbStr::eventRsvpParticipationRole());
 
71
        filterableProperties.insert(QOrganizerEventRsvp::FieldParticipationStatus,
 
72
                                    QOrganizerJsonDbStr::eventRsvpParticipationStatus());
 
73
        filterableProperties.insert(QOrganizerEventRsvp::FieldResponseDate,
 
74
                                    QOrganizerJsonDbStr::eventRsvpResponseDate());
 
75
        filterableProperties.insert(QOrganizerEventRsvp::FieldResponseDeadline,
 
76
                                    QOrganizerJsonDbStr::eventRsvpResponseDeadline());
 
77
        filterableProperties.insert(QOrganizerEventRsvp::FieldResponseRequirement,
 
78
                                    QOrganizerJsonDbStr::eventRsvpResponseRequirement());
 
79
        filterableProperties.insert(QOrganizerEventTime::FieldAllDay,
 
80
                                    QOrganizerJsonDbStr::eventIsAllDay());
 
81
        filterableProperties.insert(QOrganizerEventTime::FieldEndDateTime,
 
82
                                    QOrganizerJsonDbStr::eventEndDateTime());
 
83
        filterableProperties.insert(QOrganizerEventTime::FieldStartDateTime,
 
84
                                    QOrganizerJsonDbStr::eventStartDateTime());
 
85
        filterableProperties.insert(QOrganizerItemGuid::FieldGuid,
 
86
                                    QOrganizerJsonDbStr::itemGuid());
 
87
        filterableProperties.insert(QOrganizerItemLocation::FieldLabel,
 
88
                                    QString(QStringLiteral("%1.%2")
 
89
                                            .arg(QOrganizerJsonDbStr::eventLocation())
 
90
                                            .arg(QOrganizerJsonDbStr::eventLocationDisplayName()))
 
91
                                   );
 
92
        filterableProperties.insert(QOrganizerItemLocation::FieldLatitude,
 
93
                                    QString(QStringLiteral("%1.%2.%3")
 
94
                                            .arg(QOrganizerJsonDbStr::eventLocation())
 
95
                                            .arg(QOrganizerJsonDbStr::eventLocationGeo())
 
96
                                            .arg(QOrganizerJsonDbStr::eventLocationGeoLatitude()))
 
97
                                   );
 
98
        filterableProperties.insert(QOrganizerItemLocation::FieldLongitude,
 
99
                                    QString(QStringLiteral("%1.%2.%3")
 
100
                                            .arg(QOrganizerJsonDbStr::eventLocation())
 
101
                                            .arg(QOrganizerJsonDbStr::eventLocationGeo())
 
102
                                            .arg(QOrganizerJsonDbStr::eventLocationGeoLongitude()))
 
103
                                   );
 
104
        filterableProperties.insert(QOrganizerItemPriority::FieldPriority,
 
105
                                    QOrganizerJsonDbStr::itemPriority());
 
106
        filterableProperties.insert(QOrganizerItemTag::FieldTag,
 
107
                                    QOrganizerJsonDbStr::itemTags());
 
108
        filterableProperties.insert(QOrganizerTodoProgress::FieldFinishedDateTime,
 
109
                                    QOrganizerJsonDbStr::todoFinishedDateTime());
 
110
        filterableProperties.insert(QOrganizerTodoProgress::FieldPercentageComplete,
 
111
                                    QOrganizerJsonDbStr::todoProgressPercentage());
 
112
        filterableProperties.insert(QOrganizerTodoProgress::FieldStatus,
 
113
                                    QOrganizerJsonDbStr::todoStatus());
 
114
        filterableProperties.insert(QOrganizerTodoTime::FieldAllDay,
 
115
                                    QOrganizerJsonDbStr::todoIsAllDay());
 
116
        filterableProperties.insert(QOrganizerTodoTime::FieldDueDateTime,
 
117
                                    QOrganizerJsonDbStr::todoDueDateTime());
 
118
        filterableProperties.insert(QOrganizerTodoTime::FieldStartDateTime,
 
119
                                    QOrganizerJsonDbStr::todoStartDateTime());
 
120
    };
 
121
    return filterableProperties;
 
122
}
 
123
 
 
124
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerPriorityEnumMap()
 
125
{
 
126
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
127
        {QOrganizerItemPriority::UnknownPriority,        QString(QStringLiteral("UnknownPriority"))},
 
128
        {QOrganizerItemPriority::ExtremelyHighPriority,  QString(QStringLiteral("HighestPriority"))},
 
129
        {QOrganizerItemPriority::ExtremelyHighPriority,  QString(QStringLiteral("ExtremelyHighPriority"))},
 
130
        {QOrganizerItemPriority::VeryHighPriority,       QString(QStringLiteral("VeryHighPriority"))},
 
131
        {QOrganizerItemPriority::HighPriority,           QString(QStringLiteral("HighPriority"))},
 
132
        {QOrganizerItemPriority::MediumPriority,         QString(QStringLiteral("MediumPriority"))},
 
133
        {QOrganizerItemPriority::LowPriority,            QString(QStringLiteral("LowPriority"))},
 
134
        {QOrganizerItemPriority::VeryLowPriority,        QString(QStringLiteral("VeryLowPriority"))},
 
135
        {QOrganizerItemPriority::ExtremelyLowPriority,   QString(QStringLiteral("ExtremelyLowPriority"))},
 
136
        {QOrganizerItemPriority::LowestPriority,         QString(QStringLiteral("LowestPriority"))},
 
137
        {enumMapEnd,                                     QString::null}
 
138
    };
 
139
    return map;
 
140
}
 
141
 
 
142
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerFrequencyEnumMap()
 
143
{
 
144
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
145
        {QOrganizerRecurrenceRule::Invalid,              QString(QStringLiteral("Invalid"))},
 
146
        {QOrganizerRecurrenceRule::Daily,                QString(QStringLiteral("Daily"))},
 
147
        {QOrganizerRecurrenceRule::Weekly,               QString(QStringLiteral("Weekly"))},
 
148
        {QOrganizerRecurrenceRule::Monthly,              QString(QStringLiteral("Monthly"))},
 
149
        {QOrganizerRecurrenceRule::Yearly,               QString(QStringLiteral("Yearly"))},
 
150
        {enumMapEnd,                                     QString::null}
 
151
    };
 
152
    return map;
 
153
}
 
154
 
 
155
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerDayEnumMap()
 
156
{
 
157
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
158
        {Qt::Monday,                                     QString(QStringLiteral("Monday"))},
 
159
        {Qt::Tuesday,                                    QString(QStringLiteral("Tuesday"))},
 
160
        {Qt::Wednesday,                                  QString(QStringLiteral("Wednesday"))},
 
161
        {Qt::Thursday,                                   QString(QStringLiteral("Thursday"))},
 
162
        {Qt::Friday,                                     QString(QStringLiteral("Friday"))},
 
163
        {Qt::Saturday,                                   QString(QStringLiteral("Saturday"))},
 
164
        {Qt::Sunday,                                     QString(QStringLiteral("Sunday"))},
 
165
        {enumMapEnd,                                     QString::null}
 
166
    };
 
167
    return map;
 
168
}
 
169
 
 
170
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerMonthEnumMap()
 
171
{
 
172
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
173
        {QOrganizerRecurrenceRule::January,              QString(QStringLiteral("January"))},
 
174
        {QOrganizerRecurrenceRule::February,             QString(QStringLiteral("February"))},
 
175
        {QOrganizerRecurrenceRule::March,                QString(QStringLiteral("March"))},
 
176
        {QOrganizerRecurrenceRule::April,                QString(QStringLiteral("April"))},
 
177
        {QOrganizerRecurrenceRule::May,                  QString(QStringLiteral("May"))},
 
178
        {QOrganizerRecurrenceRule::June,                 QString(QStringLiteral("June"))},
 
179
        {QOrganizerRecurrenceRule::July,                 QString(QStringLiteral("July"))},
 
180
        {QOrganizerRecurrenceRule::August,               QString(QStringLiteral("August"))},
 
181
        {QOrganizerRecurrenceRule::September,            QString(QStringLiteral("September"))},
 
182
        {QOrganizerRecurrenceRule::October,              QString(QStringLiteral("October"))},
 
183
        {QOrganizerRecurrenceRule::November,             QString(QStringLiteral("November"))},
 
184
        {QOrganizerRecurrenceRule::December,             QString(QStringLiteral("December"))},
 
185
        {enumMapEnd,                                     QString::null}
 
186
    };
 
187
    return map;
 
188
}
 
189
 
 
190
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerParticipationStatusMap()
 
191
{
 
192
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
193
        {QOrganizerEventAttendee::StatusUnknown,         QString(QStringLiteral("Unknown"))},
 
194
        {QOrganizerEventAttendee::StatusAccepted,        QString(QStringLiteral("Accepted"))},
 
195
        {QOrganizerEventAttendee::StatusDeclined,        QString(QStringLiteral("Declined"))},
 
196
        {QOrganizerEventAttendee::StatusTentative,       QString(QStringLiteral("Tentative"))},
 
197
        {QOrganizerEventAttendee::StatusDelegated,       QString(QStringLiteral("Delegated"))},
 
198
        {QOrganizerEventAttendee::StatusInProcess,       QString(QStringLiteral("InProcess"))},
 
199
        {QOrganizerEventAttendee::StatusCompleted,       QString(QStringLiteral("Completed"))},
 
200
        {enumMapEnd,                                     QString::null}
 
201
    };
 
202
    return map;
 
203
}
 
204
 
 
205
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerParticipationRoleMap()
 
206
{
 
207
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
208
        {QOrganizerEventAttendee::RoleUnknown,             QString(QStringLiteral("Unknown"))},
 
209
        {QOrganizerEventAttendee::RoleOrganizer,           QString(QStringLiteral("Organizer"))},
 
210
        {QOrganizerEventAttendee::RoleChairperson,         QString(QStringLiteral("Chairperson"))},
 
211
        {QOrganizerEventAttendee::RoleHost,                QString(QStringLiteral("Host"))},
 
212
        {QOrganizerEventAttendee::RoleRequiredParticipant, QString(QStringLiteral("RequiredParticipant"))},
 
213
        {QOrganizerEventAttendee::RoleOptionalParticipant, QString(QStringLiteral("OptionalParticipant"))},
 
214
        {QOrganizerEventAttendee::RoleNonParticipant,      QString(QStringLiteral("NonParticipant"))},
 
215
        {enumMapEnd,                                       QString::null}
 
216
    };
 
217
    return map;
 
218
}
 
219
 
 
220
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerResponseRequirementMap()
 
221
{
 
222
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
223
        {QOrganizerEventRsvp::ResponseNotRequired,         QString(QStringLiteral("NotRequired"))},
 
224
        {QOrganizerEventRsvp::ResponseRequired,            QString(QStringLiteral("Required"))},
 
225
        {enumMapEnd,                                       QString::null}
 
226
    };
 
227
    return map;
 
228
}
 
229
 
 
230
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerItemTypeMap()
 
231
{
 
232
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
233
        {QOrganizerItemType::TypeUndefined,                 QString(QStringLiteral("Undefined"))},
 
234
        {QOrganizerItemType::TypeEvent,                     QString(QStringLiteral("Event"))},
 
235
        {QOrganizerItemType::TypeEventOccurrence,           QString(QStringLiteral("EventOccurrence"))},
 
236
        {QOrganizerItemType::TypeTodo,                      QString(QStringLiteral("Todo"))},
 
237
        {QOrganizerItemType::TypeTodoOccurrence,            QString(QStringLiteral("TodoOccurrence"))},
 
238
        {QOrganizerItemType::TypeJournal,                   QString(QStringLiteral("Journal"))},
 
239
        {QOrganizerItemType::TypeNote,                      QString(QStringLiteral("Note"))},
 
240
        {enumMapEnd,                                        QString::null}
 
241
    };
 
242
    return map;
 
243
}
 
244
 
 
245
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerTodoStatusMap()
 
246
{
 
247
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
248
        {QOrganizerTodoProgress::StatusNotStarted,          QString(QStringLiteral("NotStarted"))},
 
249
        {QOrganizerTodoProgress::StatusInProgress,          QString(QStringLiteral("InProgress"))},
 
250
        {QOrganizerTodoProgress::StatusComplete,            QString(QStringLiteral("Complete"))},
 
251
        {enumMapEnd,                                        QString::null}
 
252
    };
 
253
    return map;
 
254
}
 
255
 
 
256
const QOrganizerJsonDbEnumConversionData *QOrganizerJsonDbConverter::organizerStorageLocationMap()
 
257
{
 
258
    static const QOrganizerJsonDbEnumConversionData map[] = {
 
259
        {QOrganizerJsonDbEngine::UserDataStorage,        QString(QStringLiteral("com.nokia.mt.User"))},
 
260
        {QOrganizerJsonDbEngine::SystemStorage,          QString(QStringLiteral("com.nokia.mt.System"))},
 
261
        {enumMapEnd,                                     QString::null}
 
262
    };
 
263
    return map;
 
264
}
 
265
 
 
266
QOrganizerJsonDbConverter::QOrganizerJsonDbConverter()
 
267
{
 
268
}
 
269
 
 
270
QOrganizerManager::Error QOrganizerJsonDbConverter::jsonDbConnectionErrorToOrganizerError(QJsonDbConnection::ErrorCode error) const
 
271
{
 
272
    switch (error) {
 
273
    case QJsonDbConnection::NoError:
 
274
        return QOrganizerManager::NoError;
 
275
    }
 
276
    return QOrganizerManager::NoError;
 
277
}
 
278
 
 
279
QOrganizerManager::Error QOrganizerJsonDbConverter::jsonDbRequestErrorToOrganizerError(QJsonDbRequest::ErrorCode error) const
 
280
{
 
281
    // TODO: Add more error codes when they are available in jsondb
 
282
    // currently there is no error code for missing UUID
 
283
    switch (error) {
 
284
    case QJsonDbRequest::NoError:
 
285
        return QOrganizerManager::NoError;
 
286
    case QJsonDbRequest::MissingObject:
 
287
        return QOrganizerManager::DoesNotExistError;
 
288
    case QJsonDbRequest::MissingType:
 
289
    case QJsonDbRequest::MissingQuery:
 
290
    case QJsonDbRequest::InvalidLimit:
 
291
        return QOrganizerManager::BadArgumentError;
 
292
    case QJsonDbRequest::InvalidPartition:
 
293
        // FIXME; We propably need to add more finegrained error inspection
 
294
        // related to partition accesses, now there is only InvalidPartition.
 
295
        return QOrganizerManager::UnspecifiedError;
 
296
    case QJsonDbRequest::DatabaseConnectionError:
 
297
        return QOrganizerManager::UnspecifiedError;
 
298
    default:
 
299
        return QOrganizerManager::UnspecifiedError;
 
300
    }
 
301
}
 
302
 
 
303
bool QOrganizerJsonDbConverter::jsonDbObjectToItem(const QJsonObject &object, QOrganizerItem *item, QOrganizerJsonDbEngine::StorageLocation storageLocation) const
 
304
{
 
305
    QJsonObject objectToParse;
 
306
 
 
307
    // must handle type before reaching the loop
 
308
    QString jsonDbType = object.value(QOrganizerJsonDbStr::jsonDbType()).toString();
 
309
    if (jsonDbType == QOrganizerJsonDbStr::jsonDbEventType()) {
 
310
        item->setType(QOrganizerItemType::TypeEvent);
 
311
    } else if (jsonDbType == QOrganizerJsonDbStr::jsonDbEventOccurrenceType()) {
 
312
        item->setType(QOrganizerItemType::TypeEventOccurrence);
 
313
    } else if (jsonDbType == QOrganizerJsonDbStr::jsonDbEventViewType()) {
 
314
        // the data is stored in the "value" field, so dirty code here ;)
 
315
        objectToParse = object.value(QOrganizerJsonDbStr::jsonDbValue()).toObject();
 
316
        if (!objectToParse.value("isVisible").toBool())
 
317
            return false;
 
318
        objectToParse.insert(QOrganizerJsonDbStr::jsonDbUuid(), object.value(QOrganizerJsonDbStr::jsonDbUuid()));
 
319
        item->setType(QOrganizerItemType::TypeEvent);
 
320
        item->setData(QOrganizerJsonDbStr::eventIsSynthetic(), true);
 
321
    } else if (jsonDbType == QOrganizerJsonDbStr::jsonDbTodoType()) {
 
322
        item->setType(QOrganizerItemType::TypeTodo);
 
323
    } else if (jsonDbType == QOrganizerJsonDbStr::jsonDbTodoOccurrenceType()) {
 
324
        item->setType(QOrganizerItemType::TypeTodoOccurrence);
 
325
    } else {
 
326
        return false;
 
327
    }
 
328
 
 
329
    if (objectToParse.isEmpty())
 
330
        objectToParse = object;
 
331
 
 
332
    // other mandatory fields
 
333
    bool hasCollectionId(false);
 
334
    bool hasGuid(false);
 
335
    bool hasItemId(false);
 
336
    bool hasItemVersion(false);
 
337
 
 
338
    // go through all fields
 
339
    QJsonObject::const_iterator i = objectToParse.constBegin();
 
340
    while (i != objectToParse.constEnd()) {
 
341
        if (i.key() == QOrganizerJsonDbStr::jsonDbUuid()) {
 
342
            QString jsonDbUuid = i.value().toString();
 
343
            if (jsonDbUuid.isEmpty())
 
344
                return false;
 
345
            QOrganizerJsonDbItemId *jsondbItemId = new QOrganizerJsonDbItemId();
 
346
            jsondbItemId->setJsonDbUuid(jsonDbUuid);
 
347
            jsondbItemId->setStorageLocation(storageLocation);
 
348
            item->setId(QOrganizerItemId(jsondbItemId));
 
349
            hasItemId = true;
 
350
        } else if (i.key() == QOrganizerJsonDbStr::itemCollectionUuid()) {
 
351
            QString jsonDbCollectionIdStr = i.value().toString();
 
352
            if (jsonDbCollectionIdStr.isEmpty())
 
353
                return false;
 
354
 
 
355
            QOrganizerJsonDbCollectionId *jsondbCollId = new QOrganizerJsonDbCollectionId();
 
356
            jsondbCollId->setJsonDbUuid(jsonDbCollectionIdStr);
 
357
            jsondbCollId->setStorageLocation(storageLocation);
 
358
            item->setCollectionId(QOrganizerCollectionId(jsondbCollId));
 
359
            hasCollectionId = true;
 
360
 
 
361
        } else if (i.key() == QOrganizerJsonDbStr::itemGuid()) {
 
362
            QString guid = i.value().toString();
 
363
            if (guid.isEmpty())
 
364
                return false;
 
365
            item->setGuid(guid);
 
366
            hasGuid = true;
 
367
        } else if (i.key() == QOrganizerJsonDbStr::itemDisplayName()) {
 
368
            QString displayLabel = i.value().toString();
 
369
            if (!displayLabel.isEmpty())
 
370
                item->setDisplayLabel(displayLabel);
 
371
        } else if (i.key() == QOrganizerJsonDbStr::itemDescription()) {
 
372
            QString description = i.value().toString();
 
373
            if (!description.isEmpty())
 
374
                item->setDescription(description);
 
375
        } else if (i.key() == QOrganizerJsonDbStr::itemComments()) {
 
376
            QJsonArray array = i.value().toArray();
 
377
            if (!array.isEmpty()) {
 
378
                QStringList comments;
 
379
                for (int j = 0; j < array.size(); ++j) {
 
380
                    QString comment = array.at(j).toString();
 
381
                    if (!comment.isEmpty())
 
382
                        comments.append(comment);
 
383
                }
 
384
                if (!comments.isEmpty())
 
385
                    item->setComments(comments);
 
386
            }
 
387
        } else if (i.key() == QOrganizerJsonDbStr::itemTags()) {
 
388
            QJsonArray array = i.value().toArray();
 
389
            if (!array.isEmpty()) {
 
390
                QStringList tags;
 
391
                for (int j = 0; j < array.size(); ++j) {
 
392
                    QString tag = array.at(j).toString();
 
393
                    if (!tag.isEmpty())
 
394
                        tags.append(tag);
 
395
                }
 
396
                if (!tags.isEmpty())
 
397
                    item->setTags(tags);
 
398
            }
 
399
        } else if (i.key() == QOrganizerJsonDbStr::itemPriority()) {
 
400
            QString jsonDbPriority = i.value().toString();
 
401
            if (!jsonDbPriority.isEmpty()) {
 
402
                QOrganizerItemPriority priority;
 
403
                priority.setPriority(static_cast<QOrganizerItemPriority::Priority>(stringToEnum(organizerPriorityEnumMap(), jsonDbPriority)));
 
404
                item->saveDetail(&priority);
 
405
            }
 
406
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRules()) {
 
407
            QSet<QOrganizerRecurrenceRule> recurrenceRules;
 
408
            QJsonArray jsonDbRecurrenceRules = i.value().toArray();
 
409
            foreach (const QJsonValue &jsonDbRecurrenceRule, jsonDbRecurrenceRules) {
 
410
                QOrganizerRecurrenceRule rule;
 
411
                jsonDbObjectToRecurrenceRule(jsonDbRecurrenceRule.toObject(), &rule);
 
412
                recurrenceRules.insert(rule);
 
413
            }
 
414
 
 
415
            if (!recurrenceRules.isEmpty()) {
 
416
                QOrganizerItemRecurrence recurrence = item->detail(QOrganizerItemDetail::TypeRecurrence);
 
417
                recurrence.setRecurrenceRules(recurrenceRules);
 
418
                item->saveDetail(&recurrence);
 
419
            }
 
420
        } else if (i.key() == QOrganizerJsonDbStr::itemExceptionRules()) {
 
421
            QSet<QOrganizerRecurrenceRule> exceptionRules;
 
422
            QJsonArray jsonDbExceptionRules = i.value().toArray();
 
423
            foreach (const QJsonValue &jsonDbExceptionRule, jsonDbExceptionRules) {
 
424
                QOrganizerRecurrenceRule rule;
 
425
                jsonDbObjectToRecurrenceRule(jsonDbExceptionRule.toObject(), &rule);
 
426
                exceptionRules.insert(rule);
 
427
            }
 
428
 
 
429
            if (!exceptionRules.isEmpty()) {
 
430
                QOrganizerItemRecurrence recurrence = item->detail(QOrganizerItemDetail::TypeRecurrence);
 
431
                recurrence.setExceptionRules(exceptionRules);
 
432
                item->saveDetail(&recurrence);
 
433
            }
 
434
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceDates()) {
 
435
            QSet<QDate> recurrenceDates;
 
436
            QJsonArray jsonDbRecurrenceDates = i.value().toArray();
 
437
            foreach (const QJsonValue &jsonDbRecurrenceDate, jsonDbRecurrenceDates) {
 
438
                QDate date = QDate::fromString(jsonDbRecurrenceDate.toString(), Qt::ISODate);
 
439
                if (date.isValid())
 
440
                    recurrenceDates.insert(date);
 
441
            }
 
442
 
 
443
            if (!recurrenceDates.isEmpty()) {
 
444
                QOrganizerItemRecurrence recurrence = item->detail(QOrganizerItemDetail::TypeRecurrence);
 
445
                recurrence.setRecurrenceDates(recurrenceDates);
 
446
                item->saveDetail(&recurrence);
 
447
            }
 
448
        } else if (i.key() == QOrganizerJsonDbStr::itemExceptionDates()) {
 
449
            QSet<QDate> exceptionDates;
 
450
            QJsonArray jsonDbExceptionDates = i.value().toArray();
 
451
            foreach (const QJsonValue &jsonDbExceptionDate, jsonDbExceptionDates) {
 
452
                QDate date = QDate::fromString(jsonDbExceptionDate.toString(), Qt::ISODate);
 
453
                if (date.isValid())
 
454
                    exceptionDates.insert(date);
 
455
            }
 
456
 
 
457
            if (!exceptionDates.isEmpty()) {
 
458
                QOrganizerItemRecurrence recurrence = item->detail(QOrganizerItemDetail::TypeRecurrence);
 
459
                recurrence.setExceptionDates(exceptionDates);
 
460
                item->saveDetail(&recurrence);
 
461
            }
 
462
        } else if (i.key() == QOrganizerJsonDbStr::eventStartDateTime()) {
 
463
            // EventStartDateTime is the same as TodoStartDateTime, thus a "hack" here ;)
 
464
            QDateTime startTime = QDateTime::fromString(i.value().toString(), Qt::ISODate);
 
465
            if (startTime.isValid()) {
 
466
                if (item->type() == QOrganizerItemType::TypeEvent
 
467
                        || item->type() == QOrganizerItemType::TypeEventOccurrence) {
 
468
                    QOrganizerEventTime eventTime = item->detail(QOrganizerItemDetail::TypeEventTime);
 
469
                    eventTime.setStartDateTime(startTime);
 
470
                    item->saveDetail(&eventTime);
 
471
                } else if (item->type() == QOrganizerItemType::TypeTodo
 
472
                           || item->type() == QOrganizerItemType::TypeTodoOccurrence) {
 
473
                    QOrganizerTodoTime todoTime = item->detail(QOrganizerItemDetail::TypeTodoTime);
 
474
                    todoTime.setStartDateTime(startTime);
 
475
                    item->saveDetail(&todoTime);
 
476
                }
 
477
            }
 
478
        } else if (i.key() == QOrganizerJsonDbStr::eventEndDateTime()) {
 
479
            QDateTime endTime = QDateTime::fromString(i.value().toString(), Qt::ISODate);
 
480
            if (endTime.isValid()) {
 
481
                QOrganizerEventTime eventTime = item->detail(QOrganizerItemDetail::TypeEventTime);
 
482
                eventTime.setEndDateTime(endTime);
 
483
                item->saveDetail(&eventTime);
 
484
            }
 
485
        } else if (i.key() == QOrganizerJsonDbStr::todoDueDateTime()) {
 
486
            QDateTime dueTime = QDateTime::fromString(i.value().toString(), Qt::ISODate);
 
487
            if (dueTime.isValid()) {
 
488
                QOrganizerTodoTime todoTime = item->detail(QOrganizerItemDetail::TypeTodoTime);
 
489
                todoTime.setDueDateTime(dueTime);
 
490
                item->saveDetail(&todoTime);
 
491
            }
 
492
        } else if (i.key() == QOrganizerJsonDbStr::eventIsAllDay()) {
 
493
            // EventIsAllDay is the same as TodoIsAllDay, thus a "hack" here ;)
 
494
            bool isAllDay = i.value().toBool();
 
495
            if (item->type() == QOrganizerItemType::TypeEvent || item->type() == QOrganizerItemType::TypeEventOccurrence) {
 
496
                QOrganizerEventTime eventTime = item->detail(QOrganizerItemDetail::TypeEventTime);
 
497
                eventTime.setAllDay(isAllDay);
 
498
                item->saveDetail(&eventTime);
 
499
            } else if (item->type() == QOrganizerItemType::TypeTodo || item->type() == QOrganizerItemType::TypeTodoOccurrence) {
 
500
                QOrganizerTodoTime todoTime = item->detail(QOrganizerItemDetail::TypeTodoTime);
 
501
                todoTime.setAllDay(isAllDay);
 
502
                item->saveDetail(&todoTime);
 
503
            }
 
504
        } else if (i.key() == QOrganizerJsonDbStr::eventAttendees()) {
 
505
            QJsonArray jsonDbAttendees = i.value().toArray();
 
506
            foreach (const QJsonValue &jsonDbAttendee, jsonDbAttendees) {
 
507
                QOrganizerEventAttendee attendee;
 
508
                jsonDbObjectToAttendeeDetail(jsonDbAttendee.toObject(), &attendee);
 
509
                if (!attendee.isEmpty())
 
510
                    item->saveDetail(&attendee);
 
511
            }
 
512
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvp()) {
 
513
            QJsonObject jsonDbRsvp = i.value().toObject();
 
514
            if (!jsonDbRsvp.isEmpty()) {
 
515
                // custom fields are supported for RSVP
 
516
                QOrganizerEventRsvp rsvp;
 
517
                QOrganizerItemExtendedDetail extendedDetail;
 
518
                jsonDbObjectToRsvpDetail(jsonDbRsvp, &rsvp, &extendedDetail);
 
519
                if (!rsvp.isEmpty())
 
520
                    item->saveDetail(&rsvp);
 
521
                if (!extendedDetail.isEmpty())
 
522
                    item->saveDetail((&extendedDetail));
 
523
            }
 
524
        } else if (i.key() == QOrganizerJsonDbStr::itemOccurrenceParent()) {
 
525
            QOrganizerItemParent parentDetail = item->detail(QOrganizerItemDetail::TypeParent);
 
526
            parentDetail.setParentId(QOrganizerItemId(new QOrganizerJsonDbItemId(i.value().toString())));
 
527
            item->saveDetail(&parentDetail);
 
528
        } else if (i.key() == QOrganizerJsonDbStr::itemOccurrenceOriginalDate()) {
 
529
            QDate originalDate = QDate::fromString(i.value().toString(), Qt::ISODate);
 
530
            if (originalDate.isValid()) {
 
531
                QOrganizerItemParent parentDetail = item->detail(QOrganizerItemDetail::TypeParent);
 
532
                parentDetail.setOriginalDate(originalDate);
 
533
                item->saveDetail(&parentDetail);
 
534
            }
 
535
        } else if (i.key() == QOrganizerJsonDbStr::itemReminder()) {
 
536
            QJsonObject jsonDbReminder = i.value().toObject();
 
537
            if (!jsonDbReminder.isEmpty()) {
 
538
                // custom fields are supported for reminders
 
539
                QOrganizerItemAudibleReminder audibleReminder;
 
540
                QOrganizerItemExtendedDetail extendedDetail;
 
541
                jsonDbObjectToAudibleReminderDetail(jsonDbReminder, &audibleReminder, &extendedDetail);
 
542
                if (!audibleReminder.isEmpty())
 
543
                    item->saveDetail(&audibleReminder);
 
544
                if (!extendedDetail.isEmpty())
 
545
                    item->saveDetail((&extendedDetail));
 
546
            }
 
547
        } else if (i.key() == QOrganizerJsonDbStr::eventLocation()) {
 
548
            QJsonObject jsonDbLocation = i.value().toObject();
 
549
            if (!jsonDbLocation.isEmpty()) {
 
550
                // custom fields are supported for reminders
 
551
                QOrganizerItemLocation location;
 
552
                QOrganizerItemExtendedDetail extendedDetail;
 
553
                jsonDbObjectToLocationDetail(jsonDbLocation, &location, &extendedDetail);
 
554
                if (!location.isEmpty())
 
555
                    item->saveDetail(&location);
 
556
                if (!extendedDetail.isEmpty())
 
557
                    item->saveDetail((&extendedDetail));
 
558
            }
 
559
        } else if (i.key() == QOrganizerJsonDbStr::jsonDbVersion()) {
 
560
            QOrganizerItemVersion itemVersion;
 
561
            jsonDbVersionToItemVersion(i.value().toString(), &itemVersion);
 
562
            if (!itemVersion.isEmpty()) {
 
563
                item->saveDetail(&itemVersion);
 
564
                hasItemVersion = true;
 
565
            }
 
566
        } else if (i.key() == QOrganizerJsonDbStr::todoFinishedDateTime()) {
 
567
            QDateTime finishedDateTime = QDateTime::fromString(i.value().toString(), Qt::ISODate);
 
568
            if (finishedDateTime.isValid()) {
 
569
                QOrganizerTodoProgress todoProgress = item->detail(QOrganizerItemDetail::TypeTodoProgress);
 
570
                todoProgress.setFinishedDateTime(finishedDateTime);
 
571
                item->saveDetail(&todoProgress);
 
572
            }
 
573
        } else if (i.key() == QOrganizerJsonDbStr::todoProgressPercentage()) {
 
574
            int progressPercentage = i.value().toDouble();
 
575
            if (progressPercentage >= 0 && progressPercentage <= 100) {
 
576
                QOrganizerTodoProgress todoProgress = item->detail(QOrganizerItemDetail::TypeTodoProgress);
 
577
                todoProgress.setPercentageComplete(progressPercentage);
 
578
                item->saveDetail(&todoProgress);
 
579
            }
 
580
        } else if (i.key() == QOrganizerJsonDbStr::todoStatus()) {
 
581
            QOrganizerTodoProgress::Status todoStatus =
 
582
                    static_cast<QOrganizerTodoProgress::Status>(stringToEnum(organizerTodoStatusMap(), i.value().toString()));
 
583
            QOrganizerTodoProgress todoProgress = item->detail(QOrganizerItemDetail::TypeTodoProgress);
 
584
            todoProgress.setStatus(todoStatus);
 
585
            item->saveDetail(&todoProgress);
 
586
        } else if (i.key() == QOrganizerJsonDbStr::jsonDbType()) {
 
587
            // skip already handled before the loop
 
588
        }  else if (i.key().at(0) == QChar('_')) {
 
589
            // skip as it's used internally
 
590
        } else {
 
591
            // TODO any other fields to filter?
 
592
            QOrganizerItemExtendedDetail extendedDetail;
 
593
            extendedDetail.setName(i.key());
 
594
            extendedDetail.setData(i.value().toVariant());
 
595
            item->saveDetail(&extendedDetail);
 
596
        }
 
597
        ++i;
 
598
    }
 
599
 
 
600
    // view object is guaranteed to be correct when generated, and missing several mandatory fields as nomral objects
 
601
    if (jsonDbType == QOrganizerJsonDbStr::jsonDbEventViewType())
 
602
        return true;
 
603
 
 
604
    return hasCollectionId && hasGuid && hasItemId && hasItemVersion;
 
605
}
 
606
 
 
607
bool QOrganizerJsonDbConverter::itemToJsonDbObject(const QOrganizerItem &item, QJsonObject *object) const
 
608
{
 
609
    const QList<QOrganizerItemDetail> details = item.details();
 
610
 
 
611
    // the first detail should always be item type
 
612
    QOrganizerItemType::ItemType itemType = static_cast<QOrganizerItemType::ItemType>(details.at(0).value(QOrganizerItemType::FieldType).toInt());
 
613
    switch (itemType) {
 
614
    case QOrganizerItemType::TypeEvent:
 
615
        object->insert(QOrganizerJsonDbStr::jsonDbType(), QOrganizerJsonDbStr::jsonDbEventType());
 
616
        break;
 
617
 
 
618
    case QOrganizerItemType::TypeEventOccurrence:
 
619
        object->insert(QOrganizerJsonDbStr::jsonDbType(), QOrganizerJsonDbStr::jsonDbEventOccurrenceType());
 
620
        break;
 
621
 
 
622
    case QOrganizerItemType::TypeTodo:
 
623
        object->insert(QOrganizerJsonDbStr::jsonDbType(), QOrganizerJsonDbStr::jsonDbTodoType());
 
624
        break;
 
625
 
 
626
    case QOrganizerItemType::TypeTodoOccurrence:
 
627
        object->insert(QOrganizerJsonDbStr::jsonDbType(), QOrganizerJsonDbStr::jsonDbTodoOccurrenceType());
 
628
        break;
 
629
 
 
630
//    case QOrganizerItemType::TypeUndefined:
 
631
//    case QOrganizerItemType::TypeJournal:
 
632
//    case QOrganizerItemType::TypeNote:
 
633
    default:
 
634
        return false;
 
635
    }
 
636
 
 
637
    // item ID
 
638
    if (!item.id().isNull())
 
639
        object->insert(QOrganizerJsonDbStr::jsonDbUuid(), QOrganizerJsonDbItemId(item.id().toString()).jsondbUuid());
 
640
 
 
641
    // collection ID has already been generated in QOrganizerJsonDbRequestThread::handleItemSaveRequest() if needed
 
642
    if (!item.collectionId().isNull())
 
643
        object->insert(QOrganizerJsonDbStr::itemCollectionUuid(), QOrganizerJsonDbCollectionId(item.collectionId().toString()).jsondbUuid());
 
644
 
 
645
    // certain details that allow multiple instances
 
646
    QJsonArray comments;
 
647
    QJsonArray tags;
 
648
    QJsonArray attendees;
 
649
 
 
650
    // go through all the supported details
 
651
    for (int i = 1; i < details.size(); ++i) {
 
652
        switch (details.at(i).type()) {
 
653
        case QOrganizerItemDetail::TypeComment: {
 
654
            QString comment = details.at(i).value(QOrganizerItemComment::FieldComment).toString();
 
655
            if (!comment.isEmpty())
 
656
                comments.append(comment);
 
657
            break;
 
658
        }
 
659
 
 
660
        case QOrganizerItemDetail::TypeDescription: {
 
661
            QString description = details.at(i).value(QOrganizerItemDescription::FieldDescription).toString();
 
662
            if (!description.isEmpty())
 
663
                object->insert(QOrganizerJsonDbStr::itemDescription(), description);
 
664
            break;
 
665
        }
 
666
 
 
667
        case QOrganizerItemDetail::TypeDisplayLabel: {
 
668
            QString displayLabel = details.at(i).value(QOrganizerItemDisplayLabel::FieldLabel).toString();
 
669
            if (!displayLabel.isEmpty())
 
670
                object->insert(QOrganizerJsonDbStr::itemDisplayName(), displayLabel);
 
671
            break;
 
672
        }
 
673
 
 
674
        case QOrganizerItemDetail::TypeExtendedDetail: {
 
675
            QString name = details.at(i).value(QOrganizerItemExtendedDetail::FieldName).toString();
 
676
            if (name.isEmpty())
 
677
                break;
 
678
 
 
679
            QJsonValue data = QJsonValue::fromVariant(details.at(i).value(QOrganizerItemExtendedDetail::FieldData));
 
680
            if (data.isNull())
 
681
                break;
 
682
 
 
683
            // custom fields are allowed for reminder, rsvp, and location
 
684
            // in such cases, those values in extended details will be merged with reminder (or other) object in JsonDb
 
685
            // for all other cases, the extended detail is stored as "name: data" in JsonDb
 
686
            if (name == QOrganizerJsonDbStr::itemReminder()
 
687
                || ((itemType == QOrganizerItemType::TypeEvent || itemType == QOrganizerItemType::TypeEventOccurrence)
 
688
                    && (name == QOrganizerJsonDbStr::eventRsvp() || name == QOrganizerJsonDbStr::eventLocation()))) {
 
689
                if (!data.isObject())
 
690
                    break;
 
691
 
 
692
                QJsonObject existing = object->value(name).toObject();
 
693
                if (existing.isEmpty()) {
 
694
                    object->insert(name, data);
 
695
                } else {
 
696
                    // combining the existing value and the value from the extended detail
 
697
                    QJsonObject::const_iterator i = existing.constBegin();
 
698
                    QJsonObject newExtendedDetailProperty = data.toObject();
 
699
                    while (i != existing.constEnd()) {
 
700
                        newExtendedDetailProperty.insert(i.key(), i.value());
 
701
                        ++i;
 
702
                    }
 
703
                    object->insert(name, newExtendedDetailProperty);
 
704
                }
 
705
                break;
 
706
            }
 
707
 
 
708
 
 
709
            object->insert(name, data);
 
710
            break;
 
711
        }
 
712
 
 
713
        case QOrganizerItemDetail::TypeGuid:
 
714
            // GUID has already been generated in QOrganizerJsonDbRequestThread::handleItemSaveRequest() if needed
 
715
            object->insert(QOrganizerJsonDbStr::itemGuid(), details.at(i).value(QOrganizerItemGuid::FieldGuid).toString());
 
716
            break;
 
717
 
 
718
        case QOrganizerItemDetail::TypeLocation: {
 
719
            // in JsonDb, only events can have locations
 
720
            if (itemType != QOrganizerItemType::TypeEvent && itemType != QOrganizerItemType::TypeEventOccurrence)
 
721
                break;
 
722
            QJsonObject jsonDbLocation;
 
723
            locationDetailToJsonDbObject(details.at(i), &jsonDbLocation);
 
724
            if (!jsonDbLocation.isEmpty()) {
 
725
                // check for possible custom fields
 
726
                QJsonObject location = object->value(QOrganizerJsonDbStr::eventLocation()).toObject();
 
727
                if (location.isEmpty()) {
 
728
                    object->insert(QOrganizerJsonDbStr::eventLocation(), jsonDbLocation);
 
729
                } else {
 
730
                    QJsonObject::const_iterator i = jsonDbLocation.constBegin();
 
731
                    while (i != jsonDbLocation.constEnd()) {
 
732
                        location.insert(i.key(), i.value());
 
733
                        ++i;
 
734
                    }
 
735
                    object->insert(QOrganizerJsonDbStr::eventLocation(), location);
 
736
                }
 
737
            }
 
738
            break;
 
739
        }
 
740
 
 
741
        case QOrganizerItemDetail::TypePriority: {
 
742
            if (!details.at(i).isEmpty()) {
 
743
                object->insert(QOrganizerJsonDbStr::itemPriority(),
 
744
                               enumToString(organizerPriorityEnumMap(),
 
745
                                            static_cast<QOrganizerItemPriority::Priority>(details.at(i).value(QOrganizerItemPriority::FieldPriority).toInt())));
 
746
            }
 
747
            break;
 
748
        }
 
749
 
 
750
        case QOrganizerItemDetail::TypeRecurrence: {
 
751
            if (itemType != QOrganizerItemType::TypeEvent && itemType != QOrganizerItemType::TypeTodo)
 
752
                break;
 
753
            const QMap<int, QVariant> values = details.at(i).values();
 
754
            QMap<int, QVariant>::const_iterator j = values.constBegin();
 
755
            while (j != values.constEnd()) {
 
756
                switch (j.key()) {
 
757
                case QOrganizerItemRecurrence::FieldExceptionDates: {
 
758
                    QJsonArray exceptionDates;
 
759
                    QSet<QDate> dates = j.value().value<QSet<QDate> >();
 
760
                    foreach (const QDate &date, dates) {
 
761
                        if (date.isValid())
 
762
                            exceptionDates.append(date.toString(Qt::ISODate));
 
763
                    }
 
764
                    if (!exceptionDates.isEmpty())
 
765
                        object->insert(QOrganizerJsonDbStr::itemExceptionDates(), exceptionDates);
 
766
                    break;
 
767
                }
 
768
                case QOrganizerItemRecurrence::FieldRecurrenceDates: {
 
769
                    QJsonArray recurrenceDates;
 
770
                    QSet<QDate> dates = j.value().value<QSet<QDate> >();
 
771
                    foreach (const QDate &date, dates) {
 
772
                        if (date.isValid())
 
773
                            recurrenceDates.append(date.toString(Qt::ISODate));
 
774
                    }
 
775
                    if (!recurrenceDates.isEmpty())
 
776
                        object->insert(QOrganizerJsonDbStr::itemRecurrenceDates(), recurrenceDates);
 
777
                    break;
 
778
                }
 
779
                case QOrganizerItemRecurrence::FieldExceptionRules: {
 
780
                    QJsonArray exceptionRules;
 
781
                    QSet<QOrganizerRecurrenceRule> rules = j.value().value<QSet<QOrganizerRecurrenceRule> >();
 
782
                    foreach (const QOrganizerRecurrenceRule &rule, rules) {
 
783
                        QJsonObject exceptionRuleObject;
 
784
                        recurrenceRuleToJsonDbObject(rule, &exceptionRuleObject);
 
785
                        if (!exceptionRuleObject.isEmpty())
 
786
                            exceptionRules.append(exceptionRuleObject);
 
787
                    }
 
788
                    if (!exceptionRules.isEmpty())
 
789
                        object->insert(QOrganizerJsonDbStr::itemExceptionRules(), exceptionRules);
 
790
                    break;
 
791
                }
 
792
                case QOrganizerItemRecurrence::FieldRecurrenceRules: {
 
793
                    QJsonArray recurrenceRules;
 
794
                    QSet<QOrganizerRecurrenceRule> rules = j.value().value<QSet<QOrganizerRecurrenceRule> >();
 
795
                    foreach (const QOrganizerRecurrenceRule &rule, rules) {
 
796
                        QJsonObject recurrenceRuleObject;
 
797
                        recurrenceRuleToJsonDbObject(rule, &recurrenceRuleObject);
 
798
                        if (!recurrenceRuleObject.isEmpty())
 
799
                            recurrenceRules.append(recurrenceRuleObject);
 
800
                    }
 
801
                    if (!recurrenceRules.isEmpty())
 
802
                        object->insert(QOrganizerJsonDbStr::itemRecurrenceRules(), recurrenceRules);
 
803
                    break;
 
804
                }
 
805
                default:
 
806
                    break;
 
807
                }
 
808
                ++j;
 
809
            }
 
810
            break;
 
811
        }
 
812
 
 
813
        case QOrganizerItemDetail::TypeTag: {
 
814
            QString tag = details.at(i).value(QOrganizerItemTag::FieldTag).toString();
 
815
            if (!tag.isEmpty())
 
816
                tags.append(tag);
 
817
            break;
 
818
        }
 
819
 
 
820
        case QOrganizerItemDetail::TypeAudibleReminder: {
 
821
            QJsonObject jsonDbAudibleReminder;
 
822
            audibleReminderDetailToJsonDbObject(details.at(i), &jsonDbAudibleReminder);
 
823
            if (!jsonDbAudibleReminder.isEmpty()) {
 
824
                // check for possible custom fields
 
825
                QJsonObject reminder = object->value(QOrganizerJsonDbStr::itemReminder()).toObject();
 
826
                if (reminder.isEmpty()) {
 
827
                    object->insert(QOrganizerJsonDbStr::itemReminder(), jsonDbAudibleReminder);
 
828
                } else {
 
829
                    QJsonObject::const_iterator i = jsonDbAudibleReminder.constBegin();
 
830
                    while (i != jsonDbAudibleReminder.constEnd()) {
 
831
                        reminder.insert(i.key(), i.value());
 
832
                        ++i;
 
833
                    }
 
834
                    object->insert(QOrganizerJsonDbStr::itemReminder(), reminder);
 
835
                }
 
836
            }
 
837
            break;
 
838
        }
 
839
 
 
840
        case QOrganizerItemDetail::TypeVersion: {
 
841
            QString jsonDbVersion;
 
842
            itemVersionToJsonDbVersion(details.at(i), &jsonDbVersion);
 
843
            if (!jsonDbVersion.isEmpty())
 
844
                object->insert(QOrganizerJsonDbStr::jsonDbVersion(), jsonDbVersion);
 
845
            break;
 
846
        }
 
847
 
 
848
        case QOrganizerItemDetail::TypeEventAttendee: {
 
849
            if (itemType != QOrganizerItemType::TypeEvent && itemType != QOrganizerItemType::TypeEventOccurrence)
 
850
                break;
 
851
            QJsonObject jsonDbAttendee;
 
852
            attendeeDetailToJsonDbObject(details.at(i), &jsonDbAttendee);
 
853
            if (!jsonDbAttendee.isEmpty())
 
854
                attendees.append(jsonDbAttendee);
 
855
            break;
 
856
        }
 
857
 
 
858
        case QOrganizerItemDetail::TypeEventRsvp: {
 
859
            if (itemType != QOrganizerItemType::TypeEvent && itemType != QOrganizerItemType::TypeEventOccurrence)
 
860
                break;
 
861
            QJsonObject jsonDbRsvp;
 
862
            rsvpDetailToJsonDbObject(details.at(i), &jsonDbRsvp);
 
863
            if (!jsonDbRsvp.isEmpty()) {
 
864
                // check for possible custom fields
 
865
                QJsonObject rsvp = object->value(QOrganizerJsonDbStr::eventRsvp()).toObject();
 
866
                if (rsvp.isEmpty()) {
 
867
                    object->insert(QOrganizerJsonDbStr::eventRsvp(), jsonDbRsvp);
 
868
                } else {
 
869
                    QJsonObject::const_iterator i = jsonDbRsvp.constBegin();
 
870
                    while (i != jsonDbRsvp.constEnd()) {
 
871
                        rsvp.insert(i.key(), i.value());
 
872
                        ++i;
 
873
                    }
 
874
                    object->insert(QOrganizerJsonDbStr::eventRsvp(), rsvp);
 
875
                }
 
876
            }
 
877
            break;
 
878
        }
 
879
 
 
880
        case QOrganizerItemDetail::TypeParent: {
 
881
            if (itemType != QOrganizerItemType::TypeEventOccurrence && itemType != QOrganizerItemType::TypeTodoOccurrence)
 
882
                break;
 
883
            const QMap<int, QVariant> values = details.at(i).values();
 
884
            QMap<int, QVariant>::const_iterator j = values.constBegin();
 
885
            while (j != values.constEnd()) {
 
886
                switch (j.key()) {
 
887
                case QOrganizerItemParent::FieldParentId: {
 
888
                    QOrganizerItemId parentId = j.value().value<QOrganizerItemId>();
 
889
                    if (!parentId.isNull()) {
 
890
                        object->insert(QOrganizerJsonDbStr::itemOccurrenceParent(), QOrganizerManagerEngine::engineItemId(parentId)->toString());
 
891
                    break;
 
892
                    }
 
893
                }
 
894
                case QOrganizerItemParent::FieldOriginalDate: {
 
895
                    QDate originalDate = j.value().toDate();
 
896
                    if (originalDate.isValid())
 
897
                        object->insert(QOrganizerJsonDbStr::itemOccurrenceOriginalDate(), originalDate.toString(Qt::ISODate));
 
898
                    break;
 
899
                }
 
900
                default:
 
901
                    break;
 
902
                }
 
903
                ++j;
 
904
            }
 
905
            break;
 
906
        }
 
907
 
 
908
        case QOrganizerItemDetail::TypeEventTime: {
 
909
            if (itemType != QOrganizerItemType::TypeEvent && itemType != QOrganizerItemType::TypeEventOccurrence)
 
910
                break;
 
911
            const QMap<int, QVariant> values = details.at(i).values();
 
912
            QMap<int, QVariant>::const_iterator j = values.constBegin();
 
913
            while (j != values.constEnd()) {
 
914
                switch (j.key()) {
 
915
                case QOrganizerEventTime::FieldStartDateTime: {
 
916
                    QDateTime startDateTime = j.value().toDateTime();
 
917
                    if (startDateTime.isValid())
 
918
                        object->insert(QOrganizerJsonDbStr::eventStartDateTime(), startDateTime.toUTC().toString(Qt::ISODate));
 
919
                    break;
 
920
                }
 
921
                case QOrganizerEventTime::FieldEndDateTime: {
 
922
                    QDateTime endDateTime = j.value().toDateTime();
 
923
                    if (endDateTime.isValid())
 
924
                        object->insert(QOrganizerJsonDbStr::eventEndDateTime(), endDateTime.toUTC().toString(Qt::ISODate));
 
925
                    break;
 
926
                }
 
927
                case QOrganizerEventTime::FieldAllDay: {
 
928
                    QVariant isAllDay = j.value();
 
929
                    if (isAllDay.canConvert(QVariant::Bool))
 
930
                        object->insert(QOrganizerJsonDbStr::eventIsAllDay(), isAllDay.toBool());
 
931
                    break;
 
932
                }
 
933
                default:
 
934
                    break;
 
935
                }
 
936
                ++j;
 
937
            }
 
938
            break;
 
939
        }
 
940
 
 
941
        case QOrganizerItemDetail::TypeTodoTime: {
 
942
            if (itemType != QOrganizerItemType::TypeTodo && itemType != QOrganizerItemType::TypeTodoOccurrence)
 
943
                break;
 
944
            const QMap<int, QVariant> values = details.at(i).values();
 
945
            QMap<int, QVariant>::const_iterator j = values.constBegin();
 
946
            while (j != values.constEnd()) {
 
947
                switch (j.key()) {
 
948
                case QOrganizerTodoTime::FieldStartDateTime: {
 
949
                    QDateTime startDateTime = j.value().toDateTime();
 
950
                    if (startDateTime.isValid())
 
951
                        object->insert(QOrganizerJsonDbStr::todoStartDateTime(), startDateTime.toUTC().toString(Qt::ISODate));
 
952
                    break;
 
953
                }
 
954
                case QOrganizerTodoTime::FieldDueDateTime: {
 
955
                    QDateTime dueDateTime = j.value().toDateTime();
 
956
                    if (dueDateTime.isValid())
 
957
                        object->insert(QOrganizerJsonDbStr::todoDueDateTime(), dueDateTime.toUTC().toString(Qt::ISODate));
 
958
                    break;
 
959
                }
 
960
                case QOrganizerTodoTime::FieldAllDay: {
 
961
                    QVariant isAllDay = j.value();
 
962
                    if (isAllDay.canConvert(QVariant::Bool))
 
963
                        object->insert(QOrganizerJsonDbStr::todoIsAllDay(), isAllDay.toBool());
 
964
                    break;
 
965
                }
 
966
                default:
 
967
                    break;
 
968
                }
 
969
                ++j;
 
970
            }
 
971
            break;
 
972
        }
 
973
 
 
974
        case QOrganizerItemDetail::TypeTodoProgress: {
 
975
            if (itemType != QOrganizerItemType::TypeTodo && itemType != QOrganizerItemType::TypeTodoOccurrence)
 
976
                break;const QMap<int, QVariant> values = details.at(i).values();
 
977
            QMap<int, QVariant>::const_iterator j = values.constBegin();
 
978
            while (j != values.constEnd()) {
 
979
                switch (j.key()) {
 
980
                case QOrganizerTodoProgress::FieldFinishedDateTime: {
 
981
                    QDateTime finishedDateTime = j.value().toDateTime();
 
982
                    if (finishedDateTime.isValid())
 
983
                        object->insert(QOrganizerJsonDbStr::todoFinishedDateTime(), finishedDateTime.toUTC().toString(Qt::ISODate));
 
984
                    break;
 
985
                }
 
986
                case QOrganizerTodoProgress::FieldPercentageComplete: {
 
987
                    int percentageComplete = j.value().toInt();
 
988
                    if (percentageComplete >= 0 && percentageComplete <= 100)
 
989
                        object->insert(QOrganizerJsonDbStr::todoProgressPercentage(), percentageComplete);
 
990
                    break;
 
991
                }
 
992
                case QOrganizerTodoProgress::FieldStatus: {
 
993
                    object->insert(QOrganizerJsonDbStr::todoStatus(),
 
994
                                   enumToString(organizerTodoStatusMap(), j.value().toInt()));
 
995
                    break;
 
996
                }
 
997
                default:
 
998
                    break;
 
999
                }
 
1000
                ++j;
 
1001
            }
 
1002
            break;
 
1003
        }
 
1004
 
 
1005
//        case QOrganizerItemDetail::TypeUndefined:
 
1006
//        case QOrganizerItemDetail::TypeClassification:
 
1007
//        case QOrganizerItemDetail::TypeItemType:
 
1008
//        case QOrganizerItemDetail::TypeTimestamp:
 
1009
//        case QOrganizerItemDetail::TypeReminder:
 
1010
//        case QOrganizerItemDetail::TypeEmailReminder:
 
1011
//        case QOrganizerItemDetail::TypeVisualReminder:
 
1012
//        case QOrganizerItemDetail::TypeJournalTime:
 
1013
        default:
 
1014
            break;
 
1015
        }
 
1016
    }
 
1017
 
 
1018
    if (!comments.isEmpty())
 
1019
        object->insert(QOrganizerJsonDbStr::itemComments(), comments);
 
1020
 
 
1021
    if (!tags.isEmpty())
 
1022
        object->insert(QOrganizerJsonDbStr::itemTags(), tags);
 
1023
 
 
1024
    if (!attendees.isEmpty())
 
1025
        object->insert(QOrganizerJsonDbStr::eventAttendees(), attendees);
 
1026
 
 
1027
    return true;
 
1028
}
 
1029
 
 
1030
void QOrganizerJsonDbConverter::attendeeDetailToJsonDbObject(const QOrganizerEventAttendee &attendeeDetail, QJsonObject *object) const
 
1031
{
 
1032
    const QMap<int, QVariant> detailValues = attendeeDetail.values();
 
1033
    QMap<int, QVariant>::const_iterator i = detailValues.constBegin();
 
1034
    while (i != detailValues.constEnd()) {
 
1035
        if (i.key() == QOrganizerEventAttendee::FieldName) {
 
1036
            QString name = i.value().toString();
 
1037
            if (!name.isEmpty())
 
1038
                object->insert(QOrganizerJsonDbStr::eventAttendeeName(), name);
 
1039
        } else if (i.key() == QOrganizerEventAttendee::FieldEmailAddress) {
 
1040
            QString email = i.value().toString();
 
1041
            if (!email.isEmpty())
 
1042
                object->insert(QOrganizerJsonDbStr::eventAttendeeEmailAddress(), email);
 
1043
        } else if (i.key() == QOrganizerEventAttendee::FieldAttendeeId) {
 
1044
            QString id = i.value().toString();
 
1045
            if (!id.isEmpty())
 
1046
                object->insert(QOrganizerJsonDbStr::eventAttendeeUuid(), id);
 
1047
        } else if (i.key() == QOrganizerEventAttendee::FieldParticipationRole) {
 
1048
            object->insert(QOrganizerJsonDbStr::eventAttendeeParticipationRole(),
 
1049
                           enumToString(organizerParticipationRoleMap(), i.value().toInt()));
 
1050
        } else if (i.key() == QOrganizerEventAttendee::FieldParticipationStatus) {
 
1051
            object->insert(QOrganizerJsonDbStr::eventAttendeeParticipationStatus(),
 
1052
                           enumToString(organizerParticipationStatusMap(), i.value().toInt()));
 
1053
        }
 
1054
        ++i;
 
1055
    }
 
1056
}
 
1057
 
 
1058
void QOrganizerJsonDbConverter::jsonDbObjectToAttendeeDetail(const QJsonObject &object, QOrganizerEventAttendee *attendeeDetail) const
 
1059
{
 
1060
    QJsonObject::const_iterator i = object.constBegin();
 
1061
    QString value;
 
1062
    while (i != object.constEnd()) {
 
1063
        if (i.key() == QOrganizerJsonDbStr::eventAttendeeName()) {
 
1064
            value = i.value().toString();
 
1065
            if (!value.isEmpty())
 
1066
                attendeeDetail->setName(value);
 
1067
        } else if (i.key() == QOrganizerJsonDbStr::eventAttendeeEmailAddress()) {
 
1068
            value = i.value().toString();
 
1069
            if (!value.isEmpty())
 
1070
                attendeeDetail->setEmailAddress(value);
 
1071
        } else if (i.key() == QOrganizerJsonDbStr::eventAttendeeUuid()) {
 
1072
            value = i.value().toString();
 
1073
            if (!value.isEmpty())
 
1074
                attendeeDetail->setAttendeeId(value);
 
1075
        } else if (i.key() == QOrganizerJsonDbStr::eventAttendeeParticipationRole()) {
 
1076
            int intValue = stringToEnum(organizerParticipationRoleMap(), i.value().toString());
 
1077
            attendeeDetail->setParticipationRole(static_cast<QOrganizerEventAttendee::ParticipationRole>(intValue));
 
1078
        } else if (i.key() == QOrganizerJsonDbStr::eventAttendeeParticipationStatus()) {
 
1079
            int intValue = stringToEnum(organizerParticipationStatusMap(), i.value().toString());
 
1080
            attendeeDetail->setParticipationStatus(static_cast<QOrganizerEventAttendee::ParticipationStatus>(intValue));
 
1081
        }
 
1082
        ++i;
 
1083
    }
 
1084
}
 
1085
 
 
1086
void QOrganizerJsonDbConverter::rsvpDetailToJsonDbObject(const QOrganizerEventRsvp &rsvpDetail, QJsonObject *object) const
 
1087
{
 
1088
    const QMap<int, QVariant> rsvpValues = rsvpDetail.values();
 
1089
    QMap<int, QVariant>::const_iterator i = rsvpValues.constBegin();
 
1090
    while (i != rsvpValues.constEnd()) {
 
1091
        if (i.key() == QOrganizerEventRsvp::FieldOrganizerName) {
 
1092
            QString organizerName = i.value().toString();
 
1093
            if (!organizerName.isEmpty())
 
1094
                object->insert(QOrganizerJsonDbStr::eventRsvpOrganizerName(), organizerName);
 
1095
        } else if (i.key() == QOrganizerEventRsvp::FieldOrganizerEmail) {
 
1096
            QString organizerEmail = i.value().toString();
 
1097
            if (!organizerEmail.isEmpty())
 
1098
                object->insert(QOrganizerJsonDbStr::eventRsvpOrganizerEmail(), organizerEmail);
 
1099
        } else if (i.key() == QOrganizerEventRsvp::FieldResponseDeadline) {
 
1100
            QDate responseDeadline = i.value().toDate();
 
1101
            if (responseDeadline.isValid())
 
1102
                object->insert(QOrganizerJsonDbStr::eventRsvpResponseDeadline(), responseDeadline.toString(Qt::ISODate));
 
1103
        } else if (i.key() == QOrganizerEventRsvp::FieldResponseDate) {
 
1104
            QDate responseDate = i.value().toDate();
 
1105
            if (responseDate.isValid())
 
1106
                object->insert(QOrganizerJsonDbStr::eventRsvpResponseDate(), responseDate.toString(Qt::ISODate));
 
1107
        } else if (i.key() == QOrganizerEventRsvp::FieldParticipationRole) {
 
1108
            object->insert(QOrganizerJsonDbStr::eventRsvpParticipationRole(),
 
1109
                           enumToString(organizerParticipationRoleMap(), i.value().toInt()));
 
1110
        } else if (i.key() == QOrganizerEventRsvp::FieldParticipationStatus) {
 
1111
            object->insert(QOrganizerJsonDbStr::eventRsvpParticipationStatus(),
 
1112
                           enumToString(organizerParticipationStatusMap(), i.value().toInt()));
 
1113
        } else if (i.key() == QOrganizerEventRsvp::FieldResponseRequirement) {
 
1114
            object->insert(QOrganizerJsonDbStr::eventRsvpResponseRequirement(),
 
1115
                           enumToString(organizerResponseRequirementMap(), i.value().toInt()));
 
1116
        }
 
1117
        ++i;
 
1118
    }
 
1119
}
 
1120
 
 
1121
void QOrganizerJsonDbConverter::jsonDbObjectToRsvpDetail(const QJsonObject &object, QOrganizerEventRsvp *rsvpDetail,
 
1122
                                                         QOrganizerItemExtendedDetail *extendedDetail) const
 
1123
{
 
1124
    QJsonObject::const_iterator i = object.constBegin();
 
1125
    QVariantMap customFields;
 
1126
    while (i != object.constEnd()) {
 
1127
        if (i.key() == QOrganizerJsonDbStr::eventRsvpOrganizerName()) {
 
1128
            QString value = i.value().toString();
 
1129
            if (!value.isEmpty())
 
1130
                rsvpDetail->setOrganizerName(value);
 
1131
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpOrganizerEmail()) {
 
1132
            QString value = i.value().toString();
 
1133
            if (!value.isEmpty())
 
1134
                rsvpDetail->setOrganizerEmail(value);
 
1135
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpResponseDeadline()) {
 
1136
            QDate date = QDate::fromString(i.value().toString(), Qt::ISODate);
 
1137
            if (date.isValid())
 
1138
                rsvpDetail->setResponseDeadline(date);
 
1139
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpResponseDate()) {
 
1140
            QDate date = QDate::fromString(i.value().toString(), Qt::ISODate);
 
1141
            if (date.isValid())
 
1142
                rsvpDetail->setResponseDate(date);
 
1143
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpParticipationRole()) {
 
1144
            int intValue = stringToEnum(organizerParticipationRoleMap(), i.value().toString());
 
1145
            rsvpDetail->setParticipationRole(static_cast<QOrganizerEventAttendee::ParticipationRole>(intValue));
 
1146
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpParticipationStatus()) {
 
1147
            int intValue = stringToEnum(organizerParticipationStatusMap(), i.value().toString());
 
1148
            rsvpDetail->setParticipationStatus(static_cast<QOrganizerEventAttendee::ParticipationStatus>(intValue));
 
1149
        } else if (i.key() == QOrganizerJsonDbStr::eventRsvpResponseRequirement()) {
 
1150
            int intValue = stringToEnum(organizerResponseRequirementMap(), i.value().toString());
 
1151
            rsvpDetail->setResponseRequirement(static_cast<QOrganizerEventRsvp::ResponseRequirement>(intValue));
 
1152
        } else {
 
1153
            customFields.insert(i.key(), i.value().toVariant());
 
1154
        }
 
1155
        ++i;
 
1156
    }
 
1157
    if (!customFields.isEmpty()) {
 
1158
        extendedDetail->setName(QOrganizerJsonDbStr::eventRsvp());
 
1159
        extendedDetail->setData(customFields);
 
1160
    }
 
1161
}
 
1162
 
 
1163
void QOrganizerJsonDbConverter::locationDetailToJsonDbObject(const QOrganizerItemLocation &locationDetail, QJsonObject *object) const
 
1164
{
 
1165
    const QMap<int, QVariant> values = locationDetail.values();
 
1166
    QMap<int, QVariant>::const_iterator i = values.constBegin();
 
1167
    QJsonObject jsonDbGeo;
 
1168
    while (i != values.constEnd()) {
 
1169
        switch (i.key()) {
 
1170
        case QOrganizerItemLocation::FieldLabel: {
 
1171
            QString label = i.value().toString();
 
1172
            if (!label.isEmpty())
 
1173
                object->insert(QOrganizerJsonDbStr::eventLocationDisplayName(), label);
 
1174
            break;
 
1175
        }
 
1176
        case QOrganizerItemLocation::FieldLatitude: {
 
1177
            QVariant latitude = i.value();
 
1178
            if (latitude.canConvert(QVariant::Double))
 
1179
                jsonDbGeo.insert(QOrganizerJsonDbStr::eventLocationGeoLatitude(), latitude.toDouble());
 
1180
            break;
 
1181
        }
 
1182
        case QOrganizerItemLocation::FieldLongitude: {
 
1183
            QVariant longitude = i.value();
 
1184
            if (longitude.canConvert(QVariant::Double))
 
1185
                jsonDbGeo.insert(QOrganizerJsonDbStr::eventLocationGeoLongitude(), longitude.toDouble());
 
1186
            break;
 
1187
        }
 
1188
        default:
 
1189
            break;
 
1190
        }
 
1191
        ++i;
 
1192
    }
 
1193
    if (!jsonDbGeo.isEmpty())
 
1194
        object->insert(QOrganizerJsonDbStr::eventLocationGeo(), jsonDbGeo);
 
1195
}
 
1196
 
 
1197
void QOrganizerJsonDbConverter::jsonDbObjectToLocationDetail(const QJsonObject &object, QOrganizerItemLocation *locationDetail,
 
1198
                                                             QOrganizerItemExtendedDetail *extendedDetail) const
 
1199
{
 
1200
    QJsonObject::const_iterator i = object.constBegin();
 
1201
    QVariantMap customFields;
 
1202
    while (i != object.constEnd()) {
 
1203
        if (i.key() == QOrganizerJsonDbStr::eventLocationDisplayName()) {
 
1204
            QString label = i.value().toString();
 
1205
            if (!label.isEmpty())
 
1206
                locationDetail->setLabel(label);
 
1207
        } else if (i.key() == QOrganizerJsonDbStr::eventLocationGeo()) {
 
1208
            QJsonObject jsonDbGeo = i.value().toObject();
 
1209
            QJsonObject::const_iterator j = jsonDbGeo.constBegin();
 
1210
            while (j != jsonDbGeo.constEnd()) {
 
1211
                if (j.key() == QOrganizerJsonDbStr::eventLocationGeoLatitude()) {
 
1212
                    if (j.value().isDouble())
 
1213
                        locationDetail->setLatitude(j.value().toDouble());
 
1214
                } else if (j.key() == QOrganizerJsonDbStr::eventLocationGeoLongitude()) {
 
1215
                    if (j.value().isDouble())
 
1216
                        locationDetail->setLongitude(j.value().toDouble());
 
1217
                }
 
1218
 
 
1219
                ++j;
 
1220
            }
 
1221
        } else {
 
1222
            customFields.insert(i.key(), i.value().toVariant());
 
1223
        }
 
1224
 
 
1225
        ++i;
 
1226
    }
 
1227
    if (!customFields.isEmpty()) {
 
1228
        extendedDetail->setName(QOrganizerJsonDbStr::eventLocation());
 
1229
        extendedDetail->setData(customFields);
 
1230
    }
 
1231
}
 
1232
 
 
1233
bool QOrganizerJsonDbConverter::jsonDbObjectToCollection(const QJsonObject &object, QOrganizerCollection *collection, bool *isDefaultCollection, QOrganizerJsonDbEngine::StorageLocation storageLocation) const
 
1234
{
 
1235
    bool hasCollectionId(false);
 
1236
 
 
1237
    QVariantMap extendedMetaData;
 
1238
    QJsonObject::const_iterator i = object.constBegin();
 
1239
    while (i != object.constEnd()) {
 
1240
        if (i.key() == QOrganizerJsonDbStr::jsonDbUuid()) {
 
1241
            QString jsonUuid = i.value().toString();
 
1242
            if (jsonUuid.isEmpty())
 
1243
                return false;
 
1244
            QOrganizerJsonDbCollectionId *jsondbCollectionId = new QOrganizerJsonDbCollectionId();
 
1245
            jsondbCollectionId->setJsonDbUuid(jsonUuid);
 
1246
            jsondbCollectionId->setStorageLocation(storageLocation);
 
1247
            collection->setId(QOrganizerCollectionId(jsondbCollectionId));
 
1248
            hasCollectionId = true;
 
1249
        } else if (i.key() == QOrganizerJsonDbStr::collectionDisplayName()) {
 
1250
            QString name = i.value().toString();
 
1251
            if (!name.isEmpty())
 
1252
                collection->setMetaData(QOrganizerCollection::KeyName, name);
 
1253
        } else if (i.key() == QOrganizerJsonDbStr::collectionDescription()) {
 
1254
            QString description = i.value().toString();
 
1255
            if (!description.isEmpty())
 
1256
                collection->setMetaData(QOrganizerCollection::KeyDescription, description);
 
1257
        } else if (i.key() == QOrganizerJsonDbStr::collectionColor()) {
 
1258
            QString color = i.value().toString();
 
1259
            if (!color.isEmpty())
 
1260
                collection->setMetaData(QOrganizerCollection::KeyColor, color);
 
1261
        } else if (i.key() == QOrganizerJsonDbStr::collectionImageUrl()) {
 
1262
            QString image = i.value().toString();
 
1263
            if (!image.isEmpty())
 
1264
                collection->setMetaData(QOrganizerCollection::KeyImage, image);
 
1265
        } else if (i.key() == QOrganizerJsonDbStr::collectionDefaultFlag()) {
 
1266
            if (i.value().isBool())
 
1267
                *isDefaultCollection = i.value().toBool();
 
1268
        } else {
 
1269
            // custom meta data
 
1270
            if (i.key().at(0) != QChar('_') && !i.key().isEmpty() && !i.value().isNull())
 
1271
                extendedMetaData.insert(i.key(), i.value().toVariant());
 
1272
        }
 
1273
 
 
1274
        ++i;
 
1275
    }
 
1276
 
 
1277
    if (!extendedMetaData.isEmpty())
 
1278
        collection->setMetaData(QOrganizerCollection::KeyExtended, extendedMetaData);
 
1279
 
 
1280
    return hasCollectionId;
 
1281
}
 
1282
 
 
1283
bool QOrganizerJsonDbConverter::collectionToJsonDbObject(const QOrganizerCollection &collection, bool isDefaultCollection, QJsonObject *object) const
 
1284
{
 
1285
    QOrganizerCollectionId collectionId = collection.id();
 
1286
    if (!collectionId.isNull()) {
 
1287
        object->insert(QOrganizerJsonDbStr::jsonDbUuid(), QOrganizerJsonDbCollectionId(collectionId.toString()).jsondbUuid());
 
1288
    }
 
1289
 
 
1290
    object->insert(QOrganizerJsonDbStr::jsonDbType(), QOrganizerJsonDbStr::jsonDbCollectionType());
 
1291
 
 
1292
    if (isDefaultCollection)
 
1293
        object->insert(QOrganizerJsonDbStr::collectionDefaultFlag(), isDefaultCollection);
 
1294
 
 
1295
    QMap<QOrganizerCollection::MetaDataKey, QVariant> metaData = collection.metaData();
 
1296
    QMap<QOrganizerCollection::MetaDataKey, QVariant>::const_iterator i = metaData.constBegin();
 
1297
    while (i != metaData.constEnd()) {
 
1298
        if (i.key() == QOrganizerCollection::KeyColor) {
 
1299
            QString colorString = i.value().toString();
 
1300
            if (!colorString.isEmpty())
 
1301
                object->insert(QOrganizerJsonDbStr::collectionColor(), colorString);
 
1302
        } else if (i.key() == QOrganizerCollection::KeyDescription) {
 
1303
            QString descriptionString = i.value().toString();
 
1304
            if (!descriptionString.isEmpty())
 
1305
                object->insert(QOrganizerJsonDbStr::collectionDescription(), descriptionString);
 
1306
        } else if (i.key() == QOrganizerCollection::KeyImage) {
 
1307
            QString imageString = i.value().toString();
 
1308
            if (!imageString.isEmpty())
 
1309
                object->insert(QOrganizerJsonDbStr::collectionImageUrl(), imageString);
 
1310
        } else if (i.key() == QOrganizerCollection::KeyName) {
 
1311
            QString displayNameString = i.value().toString();
 
1312
            if (!displayNameString.isEmpty())
 
1313
                object->insert(QOrganizerJsonDbStr::collectionDisplayName(), displayNameString);
 
1314
        } else if (i.key() == QOrganizerCollection::KeyExtended) {
 
1315
            QVariantMap variantMap = i.value().toMap();
 
1316
            if (!variantMap.isEmpty()) {
 
1317
                QVariantMap::const_iterator j = variantMap.constBegin();
 
1318
                while (j != variantMap.constEnd()) {
 
1319
                    QString valueString = j.value().toString();
 
1320
                    if (!j.key().isEmpty() && !valueString.isEmpty()
 
1321
                        && (j.key().at(0) != QChar('_') || j.key() == QOrganizerJsonDbStr::jsonDbVersion())
 
1322
                        && j.key() != QOrganizerJsonDbStr::collectionDefaultFlag()) {
 
1323
                        // XXX Should we allow complex data structure, i.e. list or map, for custom meta data?
 
1324
                        object->insert(j.key(), valueString);
 
1325
                    }
 
1326
                    ++j;
 
1327
                }
 
1328
            }
 
1329
        }
 
1330
 
 
1331
        ++i;
 
1332
    }
 
1333
 
 
1334
    return true;
 
1335
}
 
1336
 
 
1337
void QOrganizerJsonDbConverter::jsonDbVersionToItemVersion(const QString &jsonDbVersion, QOrganizerItemVersion *itemVersion) const
 
1338
{
 
1339
    QStringList jsonDbVersions = jsonDbVersion.split(QLatin1Char('-'));
 
1340
    if (jsonDbVersions.size() != 2)
 
1341
         return;
 
1342
    int version = jsonDbVersions.at(0).toInt();
 
1343
 
 
1344
    if (version > 0) {
 
1345
        itemVersion->setVersion(version);
 
1346
        itemVersion->setExtendedVersion(jsonDbVersions.at(1).toLatin1());
 
1347
    }
 
1348
}
 
1349
 
 
1350
const QStringList QOrganizerJsonDbConverter::storageLocationsFlagToStrings(const QOrganizerJsonDbEngine::StorageLocations storageLocationsFlag)
 
1351
{
 
1352
    QStringList storageLocations;
 
1353
 
 
1354
    if (QOrganizerJsonDbEngine::UserDataStorage & storageLocationsFlag)
 
1355
        storageLocations.append(enumToString(organizerStorageLocationMap(), QOrganizerJsonDbEngine::UserDataStorage));
 
1356
    if (QOrganizerJsonDbEngine::SystemStorage & storageLocationsFlag)
 
1357
        storageLocations.append(enumToString(organizerStorageLocationMap(), QOrganizerJsonDbEngine::SystemStorage));
 
1358
 
 
1359
    return storageLocations;
 
1360
}
 
1361
 
 
1362
QOrganizerJsonDbEngine::StorageLocation QOrganizerJsonDbConverter::storageLocationStringToEnum(const QString &storageLocation)
 
1363
{
 
1364
    return QOrganizerJsonDbEngine::StorageLocation(stringToEnum(organizerStorageLocationMap(), storageLocation));
 
1365
}
 
1366
 
 
1367
QOrganizerJsonDbEngine::StorageLocations QOrganizerJsonDbConverter::storageLocationListToFlag(const QList<QOrganizerJsonDbEngine::StorageLocation> storageLocationsList)
 
1368
{
 
1369
    QOrganizerJsonDbEngine::StorageLocations locationsFlag(0);
 
1370
    foreach (QOrganizerJsonDbEngine::StorageLocation location, storageLocationsList) {
 
1371
        locationsFlag |= location;
 
1372
    }
 
1373
    return locationsFlag;
 
1374
}
 
1375
 
 
1376
void QOrganizerJsonDbConverter::itemVersionToJsonDbVersion(const QOrganizerItemVersion &itemVersion, QString *jsonDbVersion) const
 
1377
{
 
1378
    int version = itemVersion.version();
 
1379
    QByteArray extendedVersion = itemVersion.extendedVersion();
 
1380
 
 
1381
    if (version > 0) {
 
1382
        *jsonDbVersion = QString::number(version) + QStringLiteral("-") + QString::fromLatin1(extendedVersion.constData());
 
1383
    }
 
1384
}
 
1385
 
 
1386
void QOrganizerJsonDbConverter::jsonDbObjectToRecurrenceRule(const QJsonObject &object, QOrganizerRecurrenceRule *rule) const
 
1387
{
 
1388
    QJsonObject::const_iterator i = object.constBegin();
 
1389
    while (i != object.constEnd()) {
 
1390
        if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleFrequency()) {
 
1391
            QString frequency = i.value().toString();
 
1392
            if (!frequency.isEmpty())
 
1393
                rule->setFrequency(static_cast<QOrganizerRecurrenceRule::Frequency>(stringToEnum(organizerFrequencyEnumMap(), frequency)));
 
1394
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleInterval()) {
 
1395
            int interval = i.value().toDouble();
 
1396
            if (interval >= 0)
 
1397
                rule->setInterval(interval);
 
1398
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleLimitCount()) {
 
1399
            int limitCount = i.value().toDouble();
 
1400
            if (limitCount >= 0)
 
1401
                rule->setLimit(limitCount);
 
1402
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleLimitDate()) {
 
1403
            QDate limitDate = QDate::fromString(i.value().toString(), Qt::ISODate);
 
1404
            if (limitDate.isValid())
 
1405
                rule->setLimit(limitDate);
 
1406
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleFirstDayOfWeek()) {
 
1407
            QString firstDayOfWeek = i.value().toString();
 
1408
            if (!firstDayOfWeek.isEmpty())
 
1409
                rule->setFirstDayOfWeek(static_cast<Qt::DayOfWeek>(stringToEnum(organizerDayEnumMap(), firstDayOfWeek)));
 
1410
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRulePositions()) {
 
1411
            QJsonArray jsonDbPositions = i.value().toArray();
 
1412
            if (!jsonDbPositions.isEmpty()) {
 
1413
                QSet<int> positionsSet;
 
1414
                foreach (const QJsonValue &jsonDbPosition, jsonDbPositions)
 
1415
                    positionsSet.insert(jsonDbPosition.toDouble());
 
1416
                rule->setPositions(positionsSet);
 
1417
            }
 
1418
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfWeek()) {
 
1419
            QJsonArray jsonDbDaysOfWeek = i.value().toArray();
 
1420
            if (!jsonDbDaysOfWeek.isEmpty()) {
 
1421
                QSet<Qt::DayOfWeek> daysOfWeek;
 
1422
                foreach (const QJsonValue &jsonDbDayOfWeek, jsonDbDaysOfWeek)
 
1423
                    daysOfWeek.insert(static_cast<Qt::DayOfWeek>(stringToEnum(organizerDayEnumMap(), jsonDbDayOfWeek.toString())));
 
1424
                rule->setDaysOfWeek(daysOfWeek);
 
1425
            }
 
1426
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfMonth()) {
 
1427
            QJsonArray jsonDbDaysOfMonth = i.value().toArray();
 
1428
            if (!jsonDbDaysOfMonth.isEmpty()) {
 
1429
                QSet<int> daysOfMonth;
 
1430
                foreach (const QJsonValue &jsonDbDayOfMonth, jsonDbDaysOfMonth)
 
1431
                    daysOfMonth.insert(jsonDbDayOfMonth.toDouble());
 
1432
                rule->setDaysOfMonth(daysOfMonth);
 
1433
            }
 
1434
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfYear()) {
 
1435
            QJsonArray jsonDbDaysOfYear = i.value().toArray();
 
1436
            if (!jsonDbDaysOfYear.isEmpty()) {
 
1437
                QSet<int> daysOfYear;
 
1438
                foreach (const QJsonValue &jsonDbDayOfYear, jsonDbDaysOfYear)
 
1439
                    daysOfYear.insert(jsonDbDayOfYear.toDouble());
 
1440
                rule->setDaysOfYear(daysOfYear);
 
1441
            }
 
1442
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleWeeksOfYear()) {
 
1443
            QJsonArray jsonDbWeeksOfYear = i.value().toArray();
 
1444
            if (!jsonDbWeeksOfYear.isEmpty()) {
 
1445
                QSet<int> weeksOfYear;
 
1446
                foreach (const QJsonValue &jsonDbWeekOfYear, jsonDbWeeksOfYear)
 
1447
                    weeksOfYear.insert(jsonDbWeekOfYear.toDouble());
 
1448
                rule->setWeeksOfYear(weeksOfYear);
 
1449
            }
 
1450
        } else if (i.key() == QOrganizerJsonDbStr::itemRecurrenceRuleMonthsOfYear()) {
 
1451
            QJsonArray jsonDbMonthsOfYear = i.value().toArray();
 
1452
            if (!jsonDbMonthsOfYear.isEmpty()) {
 
1453
                QSet<QOrganizerRecurrenceRule::Month> monthsOfYear;
 
1454
                foreach (const QJsonValue &jsonDbMonthOfYear, jsonDbMonthsOfYear)
 
1455
                    monthsOfYear.insert(static_cast<QOrganizerRecurrenceRule::Month>(stringToEnum(organizerMonthEnumMap(), jsonDbMonthOfYear.toString())));
 
1456
                rule->setMonthsOfYear(monthsOfYear);
 
1457
            }
 
1458
        }
 
1459
 
 
1460
        ++i;
 
1461
    }
 
1462
}
 
1463
 
 
1464
void QOrganizerJsonDbConverter::recurrenceRuleToJsonDbObject(const QOrganizerRecurrenceRule &rule, QJsonObject *object) const
 
1465
{
 
1466
    // Invalid is the default value, so no need to save
 
1467
    QOrganizerRecurrenceRule::Frequency frequency = rule.frequency();
 
1468
    if (frequency != QOrganizerRecurrenceRule::Invalid)
 
1469
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleFrequency(), enumToString(organizerFrequencyEnumMap(), frequency));
 
1470
 
 
1471
    // 1 is the default value, so no need to save
 
1472
    int interval = rule.interval();
 
1473
    if (interval > 1)
 
1474
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleInterval(), rule.interval());
 
1475
 
 
1476
    // only saves the limit value if it's used
 
1477
    QOrganizerRecurrenceRule::LimitType limitType = rule.limitType();
 
1478
    if (limitType == QOrganizerRecurrenceRule::CountLimit)
 
1479
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleLimitCount(), rule.limitCount());
 
1480
    else if (limitType == QOrganizerRecurrenceRule::DateLimit)
 
1481
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleLimitDate(), rule.limitDate().toString(Qt::ISODate));
 
1482
 
 
1483
    // Monday is the default value, so no need to save
 
1484
    Qt::DayOfWeek firstDayOfWeek = rule.firstDayOfWeek();
 
1485
    if (firstDayOfWeek != Qt::Monday)
 
1486
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleFirstDayOfWeek(), enumToString(organizerDayEnumMap(), firstDayOfWeek));
 
1487
 
 
1488
    QSet<int> positions = rule.positions();
 
1489
    if (!positions.isEmpty()) {
 
1490
        QJsonArray positionsList;
 
1491
        foreach (int position, positions)
 
1492
            positionsList.append(position);
 
1493
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRulePositions(), positionsList);
 
1494
    }
 
1495
 
 
1496
    QSet<Qt::DayOfWeek> daysOfWeek = rule.daysOfWeek();
 
1497
    if (!daysOfWeek.isEmpty()) {
 
1498
        QJsonArray daysOfWeekList;
 
1499
        foreach (Qt::DayOfWeek day, daysOfWeek)
 
1500
            daysOfWeekList.append(enumToString(organizerDayEnumMap(), day));
 
1501
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfWeek(), daysOfWeekList);
 
1502
    }
 
1503
 
 
1504
    QSet<int> daysOfMonth = rule.daysOfMonth();
 
1505
    if (!daysOfMonth.isEmpty()) {
 
1506
        QJsonArray daysOfMonthList;
 
1507
        foreach (int day, daysOfMonth)
 
1508
            daysOfMonthList.append(day);
 
1509
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfMonth(), daysOfMonthList);
 
1510
    }
 
1511
 
 
1512
    QSet<int> daysOfYear = rule.daysOfYear();
 
1513
    if (!daysOfYear.isEmpty()) {
 
1514
        QJsonArray daysOfYearList;
 
1515
        foreach (int day, daysOfYear)
 
1516
            daysOfYearList.append(day);
 
1517
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleDaysOfYear(), daysOfYearList);
 
1518
    }
 
1519
 
 
1520
    QSet<int> weeksOfYear = rule.weeksOfYear();
 
1521
    if (!weeksOfYear.isEmpty()) {
 
1522
        QJsonArray weeksOfYearList;
 
1523
        foreach (int week, weeksOfYear)
 
1524
            weeksOfYearList.append(week);
 
1525
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleWeeksOfYear(), weeksOfYearList);
 
1526
    }
 
1527
 
 
1528
    QSet<QOrganizerRecurrenceRule::Month> monthsOfYear = rule.monthsOfYear();
 
1529
    if (!monthsOfYear.isEmpty()) {
 
1530
        QJsonArray monthsOfYearList;
 
1531
        foreach (QOrganizerRecurrenceRule::Month month, monthsOfYear)
 
1532
            monthsOfYearList.append(enumToString(organizerMonthEnumMap(), month));
 
1533
        object->insert(QOrganizerJsonDbStr::itemRecurrenceRuleMonthsOfYear(), monthsOfYearList);
 
1534
    }
 
1535
}
 
1536
 
 
1537
void QOrganizerJsonDbConverter::audibleReminderDetailToJsonDbObject(const QOrganizerItemAudibleReminder &itemReminder, QJsonObject *object) const
 
1538
{
 
1539
    const QMap<int, QVariant> reminderValues = itemReminder.values();
 
1540
    QMap<int, QVariant>::const_iterator i = reminderValues.constBegin();
 
1541
    while (i != reminderValues.constEnd()) {
 
1542
        if (i.key() == QOrganizerItemAudibleReminder::FieldSecondsBeforeStart) {
 
1543
            int secondsBeforeStart = i.value().toInt();
 
1544
            if (secondsBeforeStart >= 0)
 
1545
                object->insert(QOrganizerJsonDbStr::itemReminderSecBeforeStart(), secondsBeforeStart);
 
1546
        } else if (i.key() == QOrganizerItemAudibleReminder::FieldRepetitionCount) {
 
1547
            int repetitionCount = i.value().toInt();
 
1548
            if (repetitionCount > 0)
 
1549
                object->insert(QOrganizerJsonDbStr::itemReminderRepetitionCount(), repetitionCount);
 
1550
        } else if (i.key() == QOrganizerItemAudibleReminder::FieldRepetitionDelay) {
 
1551
            int repetitionDelay = i.value().toInt();
 
1552
            if (repetitionDelay > 0)
 
1553
                object->insert(QOrganizerJsonDbStr::itemReminderRepetitionDelay(), repetitionDelay);
 
1554
        } else if (i.key() == QOrganizerItemAudibleReminder::FieldDataUrl) {
 
1555
            if (i.value().toUrl().isValid())
 
1556
                object->insert(QOrganizerJsonDbStr::itemReminderDataUrl(), i.value().toString());
 
1557
        }
 
1558
        ++i;
 
1559
    }
 
1560
}
 
1561
 
 
1562
void QOrganizerJsonDbConverter::jsonDbObjectToAudibleReminderDetail(const QJsonObject &object, QOrganizerItemAudibleReminder *itemReminder,
 
1563
                                                                    QOrganizerItemExtendedDetail *extendedDetail) const
 
1564
{
 
1565
    QJsonObject::const_iterator i = object.constBegin();
 
1566
    QVariantMap customFields;
 
1567
    while (i != object.constEnd()) {
 
1568
        if (i.key() == QOrganizerJsonDbStr::itemReminderSecBeforeStart()) {
 
1569
            int seconds = i.value().toDouble();
 
1570
            if (seconds >= 0)
 
1571
                itemReminder->setValue(QOrganizerItemAudibleReminder::FieldSecondsBeforeStart, seconds);
 
1572
        } else if (i.key() == QOrganizerJsonDbStr::itemReminderRepetitionCount()) {
 
1573
            int repetitionCount = i.value().toDouble();
 
1574
            if (repetitionCount > 0)
 
1575
                itemReminder->setValue(QOrganizerItemAudibleReminder::FieldRepetitionCount, repetitionCount);
 
1576
        } else if (i.key() == QOrganizerJsonDbStr::itemReminderRepetitionDelay()) {
 
1577
            int repetitionDelay = i.value().toDouble();
 
1578
            if (repetitionDelay > 0)
 
1579
                itemReminder->setValue(QOrganizerItemAudibleReminder::FieldRepetitionDelay, repetitionDelay);
 
1580
        } else if (i.key() == QOrganizerJsonDbStr::itemReminderDataUrl()) {
 
1581
            QUrl url(i.value().toString());
 
1582
            if (url.isValid())
 
1583
                itemReminder->setValue(QOrganizerItemAudibleReminder::FieldDataUrl, url);
 
1584
        } else {
 
1585
            customFields.insert(i.key(), i.value().toVariant());
 
1586
        }
 
1587
        ++i;
 
1588
    }
 
1589
    if (!customFields.isEmpty()) {
 
1590
        extendedDetail->setName(QOrganizerJsonDbStr::itemReminder());
 
1591
        extendedDetail->setData(customFields);
 
1592
    }
 
1593
}
 
1594
 
 
1595
int QOrganizerJsonDbConverter::stringToEnum(const QOrganizerJsonDbEnumConversionData* const conversionData, const QString &enumStr) const
 
1596
{
 
1597
    int i = 0;
 
1598
    while (conversionData[i].enumValue != enumMapEnd) {
 
1599
        if (conversionData[i].enumStr == enumStr)
 
1600
            return conversionData[i].enumValue;
 
1601
        i++;
 
1602
    }
 
1603
    // first index contains default values
 
1604
    return conversionData[0].enumValue;
 
1605
}
 
1606
 
 
1607
QString QOrganizerJsonDbConverter::enumToString(const QOrganizerJsonDbEnumConversionData* const conversionData, int enumValue) const
 
1608
{
 
1609
    int i = 0;
 
1610
    while (conversionData[i].enumValue != enumMapEnd) {
 
1611
        if (conversionData[i].enumValue == enumValue)
 
1612
            return conversionData[i].enumStr;
 
1613
        i++;
 
1614
    }
 
1615
    // first index contains default values
 
1616
    return conversionData[0].enumStr;
 
1617
}
 
1618
 
 
1619
bool QOrganizerJsonDbConverter::compoundFilterToJsondbQuery(const QOrganizerItemFilter &filter, QString *jsonDbQueryStr, int *typeFilterFlag) const
 
1620
{
 
1621
    bool isValidFilter = true;
 
1622
    switch (filter.type()) {
 
1623
    case QOrganizerItemFilter::IntersectionFilter: {
 
1624
        const QOrganizerItemIntersectionFilter isf(filter);
 
1625
        const QList<QOrganizerItemFilter> filterList = isf.filters();
 
1626
        foreach (const QOrganizerItemFilter &filter, filterList){
 
1627
            //query filter1 filter2 filter3 ...
 
1628
            //query [?definition="value"][?definition="value"][?definition="value"]
 
1629
            QString filterStr;
 
1630
            int subtypeFilterFlag = supportedItemTypeFlag();
 
1631
            if (compoundFilterToJsondbQuery(filter, &filterStr, &subtypeFilterFlag)) {
 
1632
                *jsonDbQueryStr += filterStr;
 
1633
                *typeFilterFlag = *typeFilterFlag & subtypeFilterFlag;
 
1634
            } else {//For intersection filter, single filter invalid means empty result from jsondb query
 
1635
                isValidFilter = false;
 
1636
            }
 
1637
        }
 
1638
        return isValidFilter;
 
1639
    }
 
1640
    case QOrganizerItemFilter::UnionFilter: {
 
1641
        const QOrganizerItemUnionFilter uf(filter);
 
1642
        const QList<QOrganizerItemFilter> filterList = uf.filters();
 
1643
        int validFilterCount = 0;
 
1644
        *typeFilterFlag = 0;
 
1645
        foreach (const QOrganizerItemFilter &filter, filterList){
 
1646
            //query filter1 filter2 filter3 ...
 
1647
            //query [?definition="value" | definition="value" | definition="value"]
 
1648
            QString filterStr;
 
1649
            int subtypeFilterFlag = supportedItemTypeFlag();
 
1650
            if (compoundFilterToJsondbQuery(filter, &filterStr, &subtypeFilterFlag)) {
 
1651
                *jsonDbQueryStr += filterStr;
 
1652
                validFilterCount ++;
 
1653
                *typeFilterFlag = *typeFilterFlag | subtypeFilterFlag;
 
1654
            } else {//For union filter, single filter invalid means we could skip this filter
 
1655
                continue;
 
1656
            }
 
1657
        }
 
1658
        if (validFilterCount > 0)
 
1659
            jsonDbQueryStr->replace(QStringLiteral("][?"), QStringLiteral(" | ")); //replace the "][?" to " | "
 
1660
        else //no valid filter means empty item list from jsondb
 
1661
            isValidFilter = false;
 
1662
        return isValidFilter;
 
1663
    }
 
1664
    default:
 
1665
        isValidFilter = singleFilterToJsondbQuery(filter, jsonDbQueryStr, typeFilterFlag);
 
1666
        break;
 
1667
    }
 
1668
 
 
1669
    if (!isValidFilter)
 
1670
        jsonDbQueryStr->clear();
 
1671
 
 
1672
    return isValidFilter;
 
1673
}
 
1674
 
 
1675
bool QOrganizerJsonDbConverter::singleFilterToJsondbQuery(const QOrganizerItemFilter& filter, QString *jsonDbQueryStr, int *typeFilterFlag) const
 
1676
{
 
1677
    bool isValidFilter = true;
 
1678
    switch (filter.type()) {
 
1679
    case QOrganizerItemFilter::CollectionFilter:
 
1680
        isValidFilter = collectionFilterToJsondbQuery(filter, jsonDbQueryStr);
 
1681
        break;
 
1682
    case QOrganizerItemFilter::IdFilter:
 
1683
        isValidFilter = idFilterToJsondbQuery(filter, jsonDbQueryStr);
 
1684
        break;
 
1685
    case QOrganizerItemFilter::DetailFieldFilter:
 
1686
        isValidFilter = detailFieldFilterToJsondbQuery(filter, jsonDbQueryStr, typeFilterFlag);
 
1687
        break;
 
1688
    case QOrganizerItemFilter::DetailFilter:
 
1689
        isValidFilter = detailFilterToJsondbQuery(filter, jsonDbQueryStr, typeFilterFlag);
 
1690
        break;
 
1691
    default:
 
1692
        break;
 
1693
    }
 
1694
 
 
1695
    return isValidFilter;
 
1696
}
 
1697
 
 
1698
QString QOrganizerJsonDbConverter::jsonDbNotificationObjectToOrganizerType(const QJsonObject &object) const
 
1699
{
 
1700
    return object.value(QOrganizerJsonDbStr::jsonDbType()).toString();
 
1701
}
 
1702
 
 
1703
QOrganizerItemId QOrganizerJsonDbConverter::jsonDbNotificationObjectToItemId(const QJsonObject &object, QOrganizerJsonDbEngine::StorageLocation storageLocation) const
 
1704
{
 
1705
    QString jsonDbUuid = object.value(QOrganizerJsonDbStr::jsonDbUuid()).toString();
 
1706
    if (jsonDbUuid.isEmpty()) {
 
1707
        return QOrganizerItemId();
 
1708
    } else {
 
1709
        QOrganizerJsonDbItemId *jsondbItemId = new QOrganizerJsonDbItemId();
 
1710
        jsondbItemId->setJsonDbUuid(jsonDbUuid);
 
1711
        jsondbItemId->setStorageLocation(storageLocation);
 
1712
        return QOrganizerItemId(jsondbItemId);
 
1713
    }
 
1714
}
 
1715
 
 
1716
QOrganizerCollectionId QOrganizerJsonDbConverter::jsonDbNotificationObjectToCollectionId(const QJsonObject &object, QOrganizerJsonDbEngine::StorageLocation storageLocation) const
 
1717
{
 
1718
    QString jsonUuid = object.value(QOrganizerJsonDbStr::jsonDbUuid()).toString();
 
1719
    if (jsonUuid.isEmpty()) {
 
1720
        return QOrganizerCollectionId();
 
1721
    } else {
 
1722
        QOrganizerJsonDbCollectionId *jsondbCollectionId = new QOrganizerJsonDbCollectionId();
 
1723
        jsondbCollectionId->setJsonDbUuid(jsonUuid);
 
1724
        jsondbCollectionId->setStorageLocation(storageLocation);
 
1725
        return QOrganizerCollectionId(jsondbCollectionId);
 
1726
    }
 
1727
}
 
1728
 
 
1729
bool QOrganizerJsonDbConverter::collectionFilterToJsondbQuery(const QOrganizerItemFilter &filter, QString *jsonDbQueryStr) const
 
1730
{
 
1731
    bool isValidFilter = true;
 
1732
    const QOrganizerItemCollectionFilter cf(filter);
 
1733
    const QSet<QOrganizerCollectionId>& ids = cf.collectionIds();
 
1734
    if (!ids.empty()) {
 
1735
        const QString idTemplate(QStringLiteral("\"%1\","));
 
1736
        QString query;
 
1737
        foreach (const QOrganizerCollectionId &id, ids) {
 
1738
            if (!id.isNull())
 
1739
                query += idTemplate.arg(QOrganizerJsonDbCollectionId(id.toString()).jsondbUuid());
 
1740
        }
 
1741
        if (!query.isEmpty()) {
 
1742
            query.truncate(query.length() - 1);
 
1743
            *jsonDbQueryStr = QOrganizerJsonDbStr::jsonDbQueryCollectionUuidsTemplate().arg(query);
 
1744
        } else {
 
1745
            isValidFilter = false;
 
1746
        }
 
1747
    } else {
 
1748
        isValidFilter = false;
 
1749
    }
 
1750
    return isValidFilter;
 
1751
}
 
1752
 
 
1753
bool QOrganizerJsonDbConverter::idFilterToJsondbQuery(const QOrganizerItemFilter &filter, QString *jsonDbQueryStr) const
 
1754
{
 
1755
    bool isValidFilter = true;
 
1756
    const QOrganizerItemIdFilter idf(filter);
 
1757
    const QList<QOrganizerItemId>& ids = idf.ids();
 
1758
    if (!ids.empty()) {
 
1759
        const QString uuidTemplate(QStringLiteral("\"%1\","));
 
1760
        QString query;
 
1761
        foreach (const QOrganizerItemId &id, ids) {
 
1762
            if (!id.isNull())
 
1763
                query += uuidTemplate.arg(QOrganizerJsonDbItemId(id.toString()).jsondbUuid());
 
1764
        }
 
1765
        if (!query.isEmpty()) {
 
1766
            query.truncate(query.length() - 1);
 
1767
            *jsonDbQueryStr = QOrganizerJsonDbStr::jsonDbQueryUuidsTemplate().arg(query);
 
1768
        } else {
 
1769
            isValidFilter = false;
 
1770
        }
 
1771
    } else {
 
1772
        isValidFilter = false;
 
1773
    }
 
1774
    return isValidFilter;
 
1775
}
 
1776
 
 
1777
bool QOrganizerJsonDbConverter::isSupportedDetailFieldFilter(
 
1778
    const QVariant &fieldValue, QOrganizerItemDetail::DetailType detailType, int detailFieldName, QOrganizerItemFilter::MatchFlags matchFlags) const
 
1779
{
 
1780
    bool isValidFilter = true;
 
1781
 
 
1782
    if (detailType == QOrganizerItemDetail::TypeUndefined && detailFieldName == -1 && fieldValue.toString().isEmpty()) {
 
1783
        // no support when any of the fields is empty
 
1784
        isValidFilter = false;
 
1785
    } else if (QOrganizerItemDetail::TypeJournalTime == detailType
 
1786
        || QOrganizerItemDetail::TypeReminder == detailType
 
1787
        || QOrganizerItemDetail::TypeAudibleReminder == detailType
 
1788
        || QOrganizerItemDetail::TypeVisualReminder == detailType
 
1789
        || QOrganizerItemDetail::TypeEmailReminder == detailType
 
1790
        || QOrganizerItemDetail::TypeRecurrence == detailType
 
1791
        || QOrganizerItemDetail::TypeTimestamp == detailType
 
1792
        || QOrganizerItemDetail::TypeEventAttendee == detailType) {
 
1793
        // filtering certain details/definitions are currently not supported
 
1794
        isValidFilter = false;
 
1795
    } else if (QOrganizerItemFilter::MatchExactly != matchFlags
 
1796
        && (QOrganizerItemDetail::TypeEventTime == detailType
 
1797
        || QOrganizerItemDetail::TypeTodoTime == detailType
 
1798
        || QOrganizerItemDetail::TypeTodoProgress == detailType
 
1799
        || QOrganizerItemDetail::TypeComment == detailType
 
1800
        || (QOrganizerItemDetail::TypeLocation == detailType && (QOrganizerItemLocation::FieldLatitude == detailFieldName || QOrganizerItemLocation::FieldLongitude == detailFieldName))
 
1801
        || QOrganizerItemDetail::TypePriority == detailType
 
1802
        || QOrganizerItemDetail::TypeItemType == detailType
 
1803
        || QOrganizerItemDetail::TypeTag == detailType
 
1804
        || QOrganizerItemDetail::TypeExtendedDetail == detailType
 
1805
        || (QOrganizerItemDetail::TypeEventRsvp == detailType && (QOrganizerEventRsvp::FieldParticipationStatus == detailFieldName
 
1806
                                                                  || QOrganizerEventRsvp::FieldParticipationRole == detailFieldName
 
1807
                                                                  || QOrganizerEventRsvp::FieldResponseRequirement == detailFieldName
 
1808
                                                                  || QOrganizerEventRsvp::FieldResponseDeadline == detailFieldName
 
1809
                                                                  || QOrganizerEventRsvp::FieldResponseDate == detailFieldName))
 
1810
        || QOrganizerItemDetail::TypeParent == detailType)) {
 
1811
        // filtering matchflags are not supported for all the types
 
1812
        isValidFilter = false;
 
1813
    } else if (QVariant::String == fieldValue.type()
 
1814
        && !(QOrganizerItemDetail::TypeComment == detailType
 
1815
        || QOrganizerItemDetail::TypeDescription == detailType
 
1816
        || QOrganizerItemDetail::TypeDisplayLabel == detailType
 
1817
        || QOrganizerItemDetail::TypeGuid == detailType
 
1818
        || (QOrganizerItemDetail::TypeLocation == detailType && QOrganizerItemLocation::FieldLabel == detailFieldName)
 
1819
        || QOrganizerItemDetail::TypeTag == detailType
 
1820
        || QOrganizerItemDetail::TypeExtendedDetail == detailType
 
1821
        || QOrganizerItemDetail::TypeItemType == detailType
 
1822
        || (QOrganizerItemDetail::TypeEventRsvp == detailType && (QOrganizerEventRsvp::FieldOrganizerEmail == detailFieldName
 
1823
                                                                  || QOrganizerEventRsvp::FieldOrganizerName == detailFieldName)))) {
 
1824
        // filtering with QString needs extra attention, not allowed for all the types
 
1825
        isValidFilter = false;
 
1826
    }
 
1827
    return isValidFilter;
 
1828
}
 
1829
 
 
1830
bool QOrganizerJsonDbConverter::detailFilterToJsondbQuery(const QOrganizerItemFilter &filter, QString *jsonDbQueryStr, int *typeFilterFlag) const
 
1831
{
 
1832
    const QOrganizerItemDetailFilter df(filter);
 
1833
    const QOrganizerItemDetail detail(df.detail());
 
1834
    const QOrganizerItemDetail::DetailType detailType (detail.type());
 
1835
 
 
1836
    //We do not currently support detailFilter on Comment or Tag details
 
1837
    if ( (detailType == QOrganizerItemDetail::TypeComment) ||
 
1838
         (detailType == QOrganizerItemDetail::TypeTag) ||
 
1839
         (detail.values().isEmpty()) )
 
1840
        return false;
 
1841
 
 
1842
    if (detailType == QOrganizerItemDetail::TypeExtendedDetail) {
 
1843
        if (detail.values().size() != 2) {
 
1844
            //Both Name and Data fields should be present, otherwise filter is invalid
 
1845
            return false;
 
1846
        } else {
 
1847
            QVariant extDetailDataValue = detail.value(QOrganizerItemExtendedDetail::FieldData);
 
1848
            QString extDetailValueString = extDetailDataValue.toString();
 
1849
            QJsonValue jsonVal = QJsonValue::fromVariant(extDetailDataValue);
 
1850
            if ( jsonVal.isString())
 
1851
                extDetailValueString = QString(QStringLiteral("\"%1\"").arg(extDetailValueString));
 
1852
            jsonDbQueryStr->append(QStringLiteral("[?%1=%2]")
 
1853
                                   .arg(detail.value(QOrganizerItemExtendedDetail::FieldName).toString())
 
1854
                                   .arg(extDetailValueString));
 
1855
            return true;
 
1856
        }
 
1857
    }
 
1858
 
 
1859
    QVariant fieldValue;
 
1860
    foreach (int field, QOrganizerJsonDbEngine::supportedDetailFields(detailType)) {
 
1861
        if (detail.hasValue(field)) {
 
1862
            fieldValue = detail.value(field);
 
1863
            if (isSupportedDetailFieldFilter(fieldValue, detailType, field, QOrganizerItemFilter::MatchExactly)) {
 
1864
                addFieldToFilterQuery(detailType, field,
 
1865
                                      fieldValue, jsonDbQueryStr,
 
1866
                                      QOrganizerItemFilter::MatchExactly,
 
1867
                                      typeFilterFlag);
 
1868
            } else {
 
1869
                return false;
 
1870
            }
 
1871
        } else {
 
1872
            jsonDbQueryStr->append(QStringLiteral("[?%1 notExists]").arg(filterablePropertyNames().value(field)));
 
1873
        }
 
1874
    }
 
1875
    return true;
 
1876
}
 
1877
 
 
1878
bool QOrganizerJsonDbConverter::detailFieldFilterToJsondbQuery(const QOrganizerItemFilter &filter, QString *jsonDbQueryStr, int *typeFilterFlag) const
 
1879
{
 
1880
    /*
 
1881
    Jsondb backend specific notes related to OrganizerItemDetailFieldFilter
 
1882
 
 
1883
    Detail specific:
 
1884
    - Currently supported details; EventTime, TodoTime, Comment, Description, DisplayLabel,
 
1885
      Gui, Location, Priority, Type, Tag, Parent and Customized(ExtendedDetail).
 
1886
    - Type-detail is mapped from enum to string, since the C++ side is using strings.
 
1887
    - Comment- and Tag-details can only be filtered with MatchExactly. No wildcards supported.
 
1888
    - Customized(ExtendedDetail)-detail can only be used to filter the custom field name, not the data value.
 
1889
      Used custom field names should be simple and clear, no spaces or special characters. Matchflags
 
1890
      are not supported either, only exact matching works.
 
1891
    - No support to filter based only on detail-type without any value. Like filter everything which has Priority-field
 
1892
      regardless of the value of the field.
 
1893
 
 
1894
    Matchflags:
 
1895
    - MatchExactly:
 
1896
      -Works with all the supported detail types/fields (above)
 
1897
      -Only same object type supported for filtering, ie strings as Dates are not supported
 
1898
    - MatchFixedString
 
1899
      - Ignores any wildcard flags as filters as exact string
 
1900
    - MatchContains, MatchEndsWith, MatchStartsWith, MatchCaseSensitive
 
1901
      - These are supported only for details having string as a value type
 
1902
      - Works only if MatchExactly or MatchFixedString are not set
 
1903
    */
 
1904
 
 
1905
    const QOrganizerItemDetailFieldFilter dff(filter);
 
1906
    const QOrganizerItemDetail::DetailType detailType(dff.detailType());
 
1907
    const int detailField(dff.detailField());
 
1908
 
 
1909
    if (isSupportedDetailFieldFilter(dff.value(), detailType, detailField, dff.matchFlags())) {
 
1910
        addFieldToFilterQuery(detailType, detailField, dff.value(), jsonDbQueryStr, dff.matchFlags(), typeFilterFlag);
 
1911
        return true;
 
1912
    } else {
 
1913
        return false;
 
1914
    }
 
1915
}
 
1916
 
 
1917
void QOrganizerJsonDbConverter::addFieldToFilterQuery(QOrganizerItemDetail::DetailType detailType,
 
1918
                                                      int detailField, const QVariant &fieldValue,
 
1919
                                                      QString *jsonDbQueryStr,
 
1920
                                                      QOrganizerItemFilter::MatchFlags matchFlags,
 
1921
                                                      int *typeFilterFlag) const
 
1922
{
 
1923
    const QString equalsQueryTemplate(QStringLiteral("[?%1=\"%2\"]"));
 
1924
    const QString equalsQueryTemplate2(QStringLiteral("[?%1=%2]"));
 
1925
    const QString equalsQueryTemplate3(QStringLiteral("[?%1.%2.%3=%4]"));
 
1926
    const QString containsQueryTemplate(QStringLiteral("[?%1 contains \"%2\"]"));
 
1927
    const QString matchFlagQueryTemplate(QStringLiteral("[?%1%2\"]"));
 
1928
    const QString matchFlagQueryTemplate2(QStringLiteral("[?%1.%2%3\"]"));
 
1929
    const QString existsQueryTemplate(QStringLiteral("[?%1 exists]"));
 
1930
    const QString valueString(fieldValue.toString());
 
1931
 
 
1932
    if (QOrganizerItemDetail::TypeEventTime == detailType) {
 
1933
        if (QOrganizerEventTime::FieldStartDateTime ==  detailField) {
 
1934
            jsonDbQueryStr->append(equalsQueryTemplate
 
1935
                .arg(QOrganizerJsonDbStr::eventStartDateTime()).arg(fieldValue.toDateTime().toUTC().toString(Qt::ISODate)));
 
1936
        } else if (QOrganizerEventTime::FieldEndDateTime == detailField) {
 
1937
            jsonDbQueryStr->append(equalsQueryTemplate
 
1938
                .arg(QOrganizerJsonDbStr::eventEndDateTime()).arg(fieldValue.toDateTime().toUTC().toString(Qt::ISODate)));
 
1939
        } else if (QOrganizerEventTime::FieldAllDay == detailField) {
 
1940
            jsonDbQueryStr->append(equalsQueryTemplate2
 
1941
                .arg(QOrganizerJsonDbStr::eventIsAllDay()).arg(valueString));
 
1942
        }
 
1943
 
 
1944
    } else if (QOrganizerItemDetail::TypeTodoTime == detailType) {
 
1945
        if (QOrganizerTodoTime::FieldStartDateTime == detailField) {
 
1946
            jsonDbQueryStr->append(equalsQueryTemplate
 
1947
                .arg(QOrganizerJsonDbStr::todoStartDateTime()).arg(fieldValue.toDateTime().toUTC().toString(Qt::ISODate)));
 
1948
        } else if (QOrganizerTodoTime::FieldDueDateTime == detailField) {
 
1949
            jsonDbQueryStr->append(equalsQueryTemplate
 
1950
                .arg(QOrganizerJsonDbStr::todoDueDateTime()).arg(fieldValue.toDateTime().toUTC().toString(Qt::ISODate)));
 
1951
        } else if (QOrganizerTodoTime::FieldAllDay == detailField) {
 
1952
            jsonDbQueryStr->append(equalsQueryTemplate2
 
1953
                .arg(QOrganizerJsonDbStr::todoIsAllDay()).arg(valueString));
 
1954
        }
 
1955
 
 
1956
    } else if (QOrganizerItemDetail::TypeTodoProgress == detailType) {
 
1957
        if (QOrganizerTodoProgress::FieldFinishedDateTime == detailField) {
 
1958
            jsonDbQueryStr->append(equalsQueryTemplate
 
1959
                .arg(QOrganizerJsonDbStr::todoFinishedDateTime())
 
1960
                .arg(fieldValue.toDateTime().toUTC().toString(Qt::ISODate)));
 
1961
        } else if (QOrganizerTodoProgress::FieldPercentageComplete == detailField) {
 
1962
            jsonDbQueryStr->append(equalsQueryTemplate2
 
1963
                .arg(QOrganizerJsonDbStr::todoProgressPercentage())
 
1964
                .arg(fieldValue.toInt()));
 
1965
        } else if (QOrganizerTodoProgress::FieldStatus == detailField) {
 
1966
            jsonDbQueryStr->append(equalsQueryTemplate
 
1967
                .arg(QOrganizerJsonDbStr::todoStatus())
 
1968
                .arg(enumToString(organizerTodoStatusMap(), fieldValue.toInt())));
 
1969
        }
 
1970
 
 
1971
    } else if (QOrganizerItemDetail::TypeComment == detailType
 
1972
        && QOrganizerItemComment::FieldComment == detailField) {
 
1973
        jsonDbQueryStr->append(containsQueryTemplate.arg(QOrganizerJsonDbStr::itemComments()).arg(valueString));
 
1974
 
 
1975
    } else if (QOrganizerItemDetail::TypeDescription == detailType
 
1976
        && QOrganizerItemDescription::FieldDescription == detailField) {
 
1977
        jsonDbQueryStr->append(matchFlagQueryTemplate
 
1978
            .arg(QOrganizerJsonDbStr::itemDescription()).arg(createMatchFlagQuery(valueString, matchFlags)));
 
1979
 
 
1980
    } else if (QOrganizerItemDetail::TypeDisplayLabel == detailType
 
1981
        && QOrganizerItemDisplayLabel::FieldLabel == detailField) {
 
1982
       jsonDbQueryStr->append(matchFlagQueryTemplate
 
1983
            .arg(QOrganizerJsonDbStr::itemDisplayName())
 
1984
            .arg(createMatchFlagQuery(valueString, matchFlags)));
 
1985
 
 
1986
    } else if (QOrganizerItemDetail::TypeGuid == detailType
 
1987
        && QOrganizerItemGuid::FieldGuid ==  detailField) {
 
1988
        jsonDbQueryStr->append(matchFlagQueryTemplate
 
1989
            .arg(QOrganizerJsonDbStr::itemGuid())
 
1990
            .arg(createMatchFlagQuery(valueString, matchFlags)));
 
1991
 
 
1992
    } else if (QOrganizerItemDetail::TypeLocation == detailType) {
 
1993
        if (QOrganizerItemLocation::FieldLabel ==  detailField) {
 
1994
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
1995
                .arg(QOrganizerJsonDbStr::eventLocation())
 
1996
                .arg(QOrganizerJsonDbStr::eventLocationDisplayName())
 
1997
                .arg(createMatchFlagQuery(valueString, matchFlags)));
 
1998
        } else if (QOrganizerItemLocation::FieldLongitude ==  detailField) {
 
1999
            jsonDbQueryStr->append(equalsQueryTemplate3
 
2000
                .arg(QOrganizerJsonDbStr::eventLocation())
 
2001
                .arg(QOrganizerJsonDbStr::eventLocationGeo())
 
2002
                .arg(QOrganizerJsonDbStr::eventLocationGeoLongitude())
 
2003
                .arg(valueString));
 
2004
        } else if (QOrganizerItemLocation::FieldLatitude ==  detailField) {
 
2005
            jsonDbQueryStr->append(equalsQueryTemplate3
 
2006
                .arg(QOrganizerJsonDbStr::eventLocation())
 
2007
                .arg(QOrganizerJsonDbStr::eventLocationGeo())
 
2008
                .arg(QOrganizerJsonDbStr::eventLocationGeoLatitude())
 
2009
                .arg(valueString));
 
2010
        }
 
2011
 
 
2012
    } else if (QOrganizerItemDetail::TypePriority == detailType
 
2013
        && QOrganizerItemPriority::FieldPriority ==  detailField) {
 
2014
        jsonDbQueryStr->append(equalsQueryTemplate
 
2015
            .arg(QOrganizerJsonDbStr::itemPriority())
 
2016
            .arg(enumToString(organizerPriorityEnumMap(), fieldValue.toInt())));
 
2017
 
 
2018
    } else if (QOrganizerItemDetail::TypeItemType == detailType
 
2019
        && QOrganizerItemType::FieldType ==  detailField) {
 
2020
        jsonDbQueryStr->append(equalsQueryTemplate
 
2021
            .arg(QOrganizerJsonDbStr::jsonDbType())
 
2022
            .arg(QOrganizerJsonDbStr::jsonDbSchemaPrefix() + enumToString(organizerItemTypeMap(), fieldValue.toInt())));
 
2023
        *typeFilterFlag = 0x01 << (fieldValue.toInt() - QOrganizerItemType::TypeUndefined);
 
2024
 
 
2025
    } else if (QOrganizerItemDetail::TypeTag == detailType
 
2026
        && QOrganizerItemTag::FieldTag == detailField) {
 
2027
        jsonDbQueryStr->append(containsQueryTemplate.arg(QOrganizerJsonDbStr::itemTags()).arg(valueString));
 
2028
 
 
2029
    } else if (QOrganizerItemDetail::TypeParent == detailType) {
 
2030
        if (QOrganizerItemParent::FieldParentId == detailField) {
 
2031
            const QOrganizerItemEngineId *itemIdPtr = QOrganizerManagerEngine::engineItemId(fieldValue.value<QOrganizerItemId>());
 
2032
            if (itemIdPtr) {
 
2033
                jsonDbQueryStr->append(equalsQueryTemplate
 
2034
                    .arg(QOrganizerJsonDbStr::itemOccurrenceParent())
 
2035
                    .arg(itemIdPtr->toString()));
 
2036
            }
 
2037
        } else if (QOrganizerItemParent::FieldOriginalDate == detailField) {
 
2038
            jsonDbQueryStr->append(equalsQueryTemplate
 
2039
                .arg(QOrganizerJsonDbStr::itemOccurrenceOriginalDate()).arg(fieldValue.toDate().toString(Qt::ISODate)));
 
2040
        }
 
2041
    } else if (QOrganizerItemDetail::TypeExtendedDetail == detailType
 
2042
         && QOrganizerItemExtendedDetail::FieldName ==  detailField) {
 
2043
        jsonDbQueryStr->append(existsQueryTemplate.arg(valueString));
 
2044
 
 
2045
    } else if (QOrganizerItemDetail::TypeEventRsvp == detailType) {
 
2046
        if (QOrganizerEventRsvp::FieldParticipationStatus == detailField) {
 
2047
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2048
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2049
                    .arg(QOrganizerJsonDbStr::eventRsvpParticipationStatus())
 
2050
                    .arg(createMatchFlagQuery(enumToString(organizerParticipationStatusMap(), fieldValue.toInt()), matchFlags)));
 
2051
        } else if (QOrganizerEventRsvp::FieldParticipationRole == detailField) {
 
2052
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2053
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2054
                    .arg(QOrganizerJsonDbStr::eventRsvpParticipationRole())
 
2055
                    .arg(createMatchFlagQuery(enumToString(organizerParticipationRoleMap(), fieldValue.toInt()), matchFlags)));
 
2056
        } else if (QOrganizerEventRsvp::FieldResponseRequirement == detailField) {
 
2057
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2058
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2059
                    .arg(QOrganizerJsonDbStr::eventRsvpResponseRequirement())
 
2060
                    .arg(createMatchFlagQuery(enumToString(organizerResponseRequirementMap(), fieldValue.toInt()), matchFlags)));
 
2061
        } else if (QOrganizerEventRsvp::FieldResponseDeadline == detailField) {
 
2062
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2063
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2064
                    .arg(QOrganizerJsonDbStr::eventRsvpResponseDeadline())
 
2065
                    .arg(createMatchFlagQuery(fieldValue.toDate().toString(Qt::ISODate), matchFlags)));
 
2066
        } else if (QOrganizerEventRsvp::FieldResponseDate == detailField) {
 
2067
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2068
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2069
                    .arg(QOrganizerJsonDbStr::eventRsvpResponseDate())
 
2070
                    .arg(createMatchFlagQuery(fieldValue.toDate().toString(Qt::ISODate), matchFlags)));
 
2071
        } else if (QOrganizerEventRsvp::FieldOrganizerName == detailField) {
 
2072
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2073
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2074
                    .arg(QOrganizerJsonDbStr::eventRsvpOrganizerName())
 
2075
                    .arg(createMatchFlagQuery(valueString, matchFlags)));
 
2076
        } else if (QOrganizerEventRsvp::FieldOrganizerEmail == detailField) {
 
2077
            jsonDbQueryStr->append(matchFlagQueryTemplate2
 
2078
                    .arg(QOrganizerJsonDbStr::eventRsvp())
 
2079
                    .arg(QOrganizerJsonDbStr::eventRsvpOrganizerEmail())
 
2080
                    .arg(createMatchFlagQuery(valueString, matchFlags)));
 
2081
        }
 
2082
    }
 
2083
}
 
2084
 
 
2085
QString QOrganizerJsonDbConverter::createMatchFlagQuery(const QString &value, QOrganizerItemFilter::MatchFlags flags) const
 
2086
{
 
2087
    // with current enumeration, 3 means both MatchContains and MatchEndsWith (QTBUG-20035)
 
2088
    const uint realMatchType = flags & 0x0F;
 
2089
    QString queryWithWildCards;
 
2090
    if (QOrganizerItemFilter::MatchExactly == flags)
 
2091
        queryWithWildCards = QStringLiteral("=\"");
 
2092
    else
 
2093
        queryWithWildCards = QStringLiteral("=~\"/");
 
2094
 
 
2095
    if (QOrganizerItemFilter::MatchContains == realMatchType || QOrganizerItemFilter::MatchEndsWith == realMatchType)
 
2096
        queryWithWildCards += QStringLiteral("*");
 
2097
 
 
2098
    queryWithWildCards += value;
 
2099
 
 
2100
    if (QOrganizerItemFilter::MatchContains == realMatchType || QOrganizerItemFilter::MatchStartsWith == realMatchType)
 
2101
        queryWithWildCards += QStringLiteral("*");
 
2102
 
 
2103
    if (QOrganizerItemFilter::MatchExactly != flags && !(QOrganizerItemFilter::MatchFixedString & flags)) {
 
2104
        queryWithWildCards += QStringLiteral("/w");
 
2105
        if (!(QOrganizerItemFilter::MatchCaseSensitive & flags))
 
2106
            queryWithWildCards += QStringLiteral("i");
 
2107
    }
 
2108
    return queryWithWildCards;
 
2109
}
 
2110
 
 
2111
int QOrganizerJsonDbConverter::supportedItemTypeFlag() const
 
2112
{
 
2113
//     int typeFilterFlag = 0x01 << QOrganizerItemType::TypeUndefined - QOrganizerItemType::TypeUndefined
 
2114
//                        + 0x01 << (QOrganizerItemType::TypeEvent - QOrganizerItemType::TypeUndefined)
 
2115
//                        + 0x01 << (QOrganizerItemType::TypeEventOccurrence - QOrganizerItemType::TypeUndefined);
 
2116
//                        + 0x01 << (QOrganizerItemType::TypeTodo - QOrganizerItemType::TypeUndefined);
 
2117
//                        + 0x01 << (QOrganizerItemType::TypeTodoOccurrence - QOrganizerItemType::TypeUndefined);
 
2118
    return 0xf1;//typeFilterFlag;
 
2119
}
 
2120
 
 
2121
bool QOrganizerJsonDbConverter::itemTypeFlagToJsonDbEventQuery(const int &flag, QString *jsonDbQueryStr)
 
2122
{
 
2123
    if (!flag)
 
2124
        return false;
 
2125
    if (supportedItemTypeFlag() == flag)
 
2126
        *jsonDbQueryStr = QOrganizerJsonDbStr::jsonDbQueryAllEventItems() + *jsonDbQueryStr;
 
2127
    else if (!((flag >> (QOrganizerItemType::TypeEvent - QOrganizerItemType::TypeUndefined)) & 0x01)
 
2128
             && !((flag >> (QOrganizerItemType::TypeEventOccurrence - QOrganizerItemType::TypeUndefined)) & 0x01)) {
 
2129
        return false;
 
2130
    }
 
2131
    return true;
 
2132
}
 
2133
 
 
2134
bool QOrganizerJsonDbConverter::itemTypeFlagToJsonDbTodoQuery(const int &flag, QString *jsonDbQueryStr)
 
2135
{
 
2136
    if (!flag)
 
2137
        return false;
 
2138
    if (supportedItemTypeFlag() == flag)
 
2139
        *jsonDbQueryStr = QOrganizerJsonDbStr::jsonDbQueryAllTodoItems() + *jsonDbQueryStr;
 
2140
    else if (!((flag >> (QOrganizerItemType::TypeTodo - QOrganizerItemType::TypeUndefined)) & 0x01)
 
2141
             && !((flag >> (QOrganizerItemType::TypeTodoOccurrence - QOrganizerItemType::TypeUndefined)) & 0x01)) {
 
2142
        return false;
 
2143
    }
 
2144
    return true;
 
2145
}
 
2146
 
 
2147
bool QOrganizerJsonDbConverter::createJsonDbQuery(const QOrganizerItemFilter &filter, const QDateTime &startTime, const QDateTime &endTime, QList<QString> *jsonDbQueryList)
 
2148
{
 
2149
    QString filterString;
 
2150
    int typeFilterFlag = supportedItemTypeFlag();
 
2151
    if (compoundFilterToJsondbQuery(filter, &filterString, &typeFilterFlag)) {
 
2152
        if (startTime.isValid() || endTime.isValid()) {
 
2153
            QString eventJsonDbQuery;
 
2154
            if (itemTypeFlagToJsonDbEventQuery(typeFilterFlag, &eventJsonDbQuery)) {
 
2155
                eventJsonDbQuery += filterString;
 
2156
                if (startTime.isValid())
 
2157
                    eventJsonDbQuery += QOrganizerJsonDbStr::jsonDbQueryEventEndDateTimeTemplate().arg(startTime.toUTC().toString(Qt::ISODate));
 
2158
                if (endTime.isValid())
 
2159
                    eventJsonDbQuery += QOrganizerJsonDbStr::jsonDbQueryEventStartDateTimeTemplate().arg(endTime.toUTC().toString(Qt::ISODate));
 
2160
                jsonDbQueryList->append(eventJsonDbQuery);
 
2161
            }
 
2162
 
 
2163
            if (itemTypeFlagToJsonDbTodoQuery(typeFilterFlag, &filterString))
 
2164
                jsonDbQueryList->append(filterString);
 
2165
        } else {
 
2166
            //No time period terms and create one request for both todo and event
 
2167
            if (supportedItemTypeFlag() == typeFilterFlag)
 
2168
                filterString = QOrganizerJsonDbStr::jsonDbQueryAllItems() + filterString;
 
2169
            jsonDbQueryList->append(filterString);
 
2170
        }
 
2171
        return true;
 
2172
    }
 
2173
    return false;
 
2174
}
 
2175
 
 
2176
QT_END_NAMESPACE_ORGANIZER