kde-playground/kdepimlibs/akonadi/searchquery.cpp
2015-04-14 21:49:29 +00:00

379 lines
10 KiB
C++

/*
Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "searchquery.h"
#include <QtCore/QVariant>
#include <KDebug>
#include <qjson/parser.h>
#include <qjson/serializer.h>
using namespace Akonadi;
class SearchTerm::Private : public QSharedData
{
public:
Private()
: QSharedData()
, condition(SearchTerm::CondEqual)
, relation(SearchTerm::RelAnd)
, isNegated(false)
{
}
Private(const Private &other)
: QSharedData(other)
, key(other.key)
, value(other.value)
, condition(other.condition)
, relation(other.relation)
, terms(other.terms)
, isNegated(other.isNegated)
{
}
bool operator==(const Private &other) const
{
return relation == other.relation
&& isNegated == other.isNegated
&& terms == other.terms
&& key == other.key
&& value == other.value
&& condition == other.condition;
}
QString key;
QVariant value;
Condition condition;
Relation relation;
QList<SearchTerm> terms;
bool isNegated;
};
class SearchQuery::Private : public QSharedData
{
public:
Private()
: QSharedData()
, limit(-1)
{
}
Private(const Private &other)
: QSharedData(other)
, rootTerm(other.rootTerm)
, limit(other.limit)
{
}
bool operator==(const Private &other) const
{
return rootTerm == other.rootTerm && limit == other.limit;
}
static QVariantMap termToJSON(const SearchTerm &term)
{
const QList<SearchTerm> &subTerms = term.subTerms();
QVariantMap termJSON;
termJSON.insert(QLatin1String("negated"), term.isNegated());
if (subTerms.isEmpty()) {
termJSON.insert(QLatin1String("key"), term.key());
termJSON.insert(QLatin1String("value"), term.value());
termJSON.insert(QLatin1String("cond"), static_cast<int>(term.condition()));
} else {
termJSON.insert(QLatin1String("rel"), static_cast<int>(term.relation()));
QVariantList subTermsJSON;
Q_FOREACH (const SearchTerm &term, subTerms) {
subTermsJSON.append(termToJSON(term));
}
termJSON.insert(QLatin1String("subTerms"), subTermsJSON);
}
return termJSON;
}
static SearchTerm JSONToTerm(const QVariantMap &json)
{
if (json.contains(QLatin1String("key"))) {
SearchTerm term(json[QLatin1String("key")].toString(),
json[QLatin1String("value")],
static_cast<SearchTerm::Condition>(json[QLatin1String("cond")].toInt()));
term.setIsNegated(json[QLatin1String("negated")].toBool());
return term;
} else if (json.contains(QLatin1String("rel"))) {
SearchTerm term(static_cast<SearchTerm::Relation>(json[QLatin1String("rel")].toInt()));
term.setIsNegated(json[QLatin1String("negated")].toBool());
const QVariantList subTermsJSON = json[QLatin1String("subTerms")].toList();
Q_FOREACH (const QVariant &subTermJSON, subTermsJSON) {
term.addSubTerm(JSONToTerm(subTermJSON.toMap()));
}
return term;
} else {
kWarning() << "Invalid JSON for term: " << json;
return SearchTerm();
}
}
SearchTerm rootTerm;
int limit;
};
SearchTerm::SearchTerm(SearchTerm::Relation relation)
: d(new Private)
{
d->relation = relation;
}
SearchTerm::SearchTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition)
: d(new Private)
{
d->relation = RelAnd;
d->key = key;
d->value = value;
d->condition = condition;
}
SearchTerm::SearchTerm(const SearchTerm &other)
: d(other.d)
{
}
SearchTerm::~SearchTerm()
{
}
SearchTerm &SearchTerm::operator=(const SearchTerm &other)
{
d = other.d;
return *this;
}
bool SearchTerm::operator==(const SearchTerm &other) const
{
return *d == *other.d;
}
bool SearchTerm::isNull() const
{
return d->key.isEmpty() && d->value.isNull() && d->terms.isEmpty();
}
QString SearchTerm::key() const
{
return d->key;
}
QVariant SearchTerm::value() const
{
return d->value;
}
SearchTerm::Condition SearchTerm::condition() const
{
return d->condition;
}
void SearchTerm::setIsNegated(bool negated)
{
d->isNegated = negated;
}
bool SearchTerm::isNegated() const
{
return d->isNegated;
}
void SearchTerm::addSubTerm(const SearchTerm &term)
{
d->terms << term;
}
QList< SearchTerm > SearchTerm::subTerms() const
{
return d->terms;
}
SearchTerm::Relation SearchTerm::relation() const
{
return d->relation;
}
SearchQuery::SearchQuery(SearchTerm::Relation rel)
: d(new Private)
{
d->rootTerm = SearchTerm(rel);
}
SearchQuery::SearchQuery(const SearchQuery &other)
: d(other.d)
{
}
SearchQuery::~SearchQuery()
{
}
SearchQuery &SearchQuery::operator=(const SearchQuery &other)
{
d = other.d;
return *this;
}
bool SearchQuery::operator==(const SearchQuery &other) const
{
return *d == *other.d;
}
bool SearchQuery::isNull() const
{
return d->rootTerm.isNull();
}
SearchTerm SearchQuery::term() const
{
return d->rootTerm;
}
void SearchQuery::addTerm(const QString &key, const QVariant &value, SearchTerm::Condition condition)
{
addTerm(SearchTerm(key, value, condition));
}
void SearchQuery::addTerm(const SearchTerm &term)
{
d->rootTerm.addSubTerm(term);
}
void SearchQuery::setTerm(const SearchTerm &term)
{
d->rootTerm = term;
}
void SearchQuery::setLimit(int limit)
{
d->limit = limit;
}
int SearchQuery::limit() const
{
return d->limit;
}
QByteArray SearchQuery::toJSON() const
{
QVariantMap root = Private::termToJSON(d->rootTerm);
root.insert(QLatin1String("limit"), d->limit);
QJson::Serializer serializer;
return serializer.serialize(root);
}
SearchQuery SearchQuery::fromJSON(const QByteArray &jsonData)
{
QJson::Parser parser;
bool ok = false;
const QVariant json = parser.parse(jsonData, &ok);
if (!ok || json.isNull()) {
return SearchQuery();
}
const QVariantMap map = json.toMap();
SearchQuery query;
query.d->rootTerm = Private::JSONToTerm(map);
if (map.contains(QLatin1String("limit"))) {
query.d->limit = map.value(QLatin1String("limit")).toInt();
}
return query;
}
QMap<EmailSearchTerm::EmailSearchField, QString> initializeMapping()
{
QMap<EmailSearchTerm::EmailSearchField, QString> mapping;
mapping.insert(EmailSearchTerm::Body, QLatin1String("body"));
mapping.insert(EmailSearchTerm::Headers, QLatin1String("headers"));
mapping.insert(EmailSearchTerm::Subject, QLatin1String("subject"));
mapping.insert(EmailSearchTerm::Message, QLatin1String("message"));
mapping.insert(EmailSearchTerm::HeaderFrom, QLatin1String("from"));
mapping.insert(EmailSearchTerm::HeaderTo, QLatin1String("to"));
mapping.insert(EmailSearchTerm::HeaderCC, QLatin1String("cc"));
mapping.insert(EmailSearchTerm::HeaderBCC, QLatin1String("bcc"));
mapping.insert(EmailSearchTerm::HeaderReplyTo, QLatin1String("replyto"));
mapping.insert(EmailSearchTerm::HeaderOrganization, QLatin1String("organization"));
mapping.insert(EmailSearchTerm::HeaderListId, QLatin1String("listid"));
mapping.insert(EmailSearchTerm::HeaderResentFrom, QLatin1String("resentfrom"));
mapping.insert(EmailSearchTerm::HeaderXLoop, QLatin1String("xloop"));
mapping.insert(EmailSearchTerm::HeaderXMailingList, QLatin1String("xmailinglist"));
mapping.insert(EmailSearchTerm::HeaderXSpamFlag, QLatin1String("xspamflag"));
mapping.insert(EmailSearchTerm::HeaderDate, QLatin1String("date"));
mapping.insert(EmailSearchTerm::HeaderOnlyDate, QLatin1String("onlydate"));
mapping.insert(EmailSearchTerm::MessageStatus, QLatin1String("messagestatus"));
mapping.insert(EmailSearchTerm::MessageTag, QLatin1String("messagetag"));
mapping.insert(EmailSearchTerm::ByteSize, QLatin1String("size"));
mapping.insert(EmailSearchTerm::Attachment, QLatin1String("attachment"));
return mapping;
}
static QMap<EmailSearchTerm::EmailSearchField, QString> emailSearchFieldMapping = initializeMapping();
EmailSearchTerm::EmailSearchTerm(EmailSearchTerm::EmailSearchField field, const QVariant &value, SearchTerm::Condition condition)
: SearchTerm(toKey(field), value, condition)
{
}
QString EmailSearchTerm::toKey(EmailSearchTerm::EmailSearchField field)
{
return emailSearchFieldMapping.value(field);
}
EmailSearchTerm::EmailSearchField EmailSearchTerm::fromKey(const QString &key)
{
return emailSearchFieldMapping.key(key);
}
QMap<ContactSearchTerm::ContactSearchField, QString> initializeContactMapping()
{
QMap<ContactSearchTerm::ContactSearchField, QString> mapping;
mapping.insert(ContactSearchTerm::Name, QLatin1String("name"));
mapping.insert(ContactSearchTerm::Nickname, QLatin1String("nickname"));
mapping.insert(ContactSearchTerm::Email, QLatin1String("email"));
mapping.insert(ContactSearchTerm::Uid, QLatin1String("uid"));
mapping.insert(ContactSearchTerm::All, QLatin1String("all"));
return mapping;
}
static QMap<ContactSearchTerm::ContactSearchField, QString> contactSearchFieldMapping = initializeContactMapping();
ContactSearchTerm::ContactSearchTerm(ContactSearchTerm::ContactSearchField field, const QVariant &value, SearchTerm::Condition condition)
: SearchTerm(toKey(field), value, condition)
{
}
QString ContactSearchTerm::toKey(ContactSearchTerm::ContactSearchField field)
{
return contactSearchFieldMapping.value(field);
}
ContactSearchTerm::ContactSearchField ContactSearchTerm::fromKey(const QString &key)
{
return contactSearchFieldMapping.key(key);
}