protocolhelper_p.h 8.02 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>

    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.
*/

20 21
#ifndef AKONADI_PROTOCOLHELPER_P_H
#define AKONADI_PROTOCOLHELPER_P_H
22

Daniel Vrátil's avatar
Daniel Vrátil committed
23 24
#include "cachepolicy.h"
#include "collection.h"
25
#include "collectionutils.h"
Daniel Vrátil's avatar
Daniel Vrátil committed
26 27 28 29 30
#include "item.h"
#include "itemfetchscope.h"
#include "sharedvaluepool_p.h"
#include "attributeentity.h"
#include "tag.h"
31

32 33
#include <akonadi/private/imapparser_p.h>
#include <akonadi/private/protocol_p.h>
34
#include <akonadi/private/scope_p.h>
35
#include <akonadi/private/tristate_p.h>
36 37 38 39

#include <boost/bind.hpp>
#include <algorithm>

40 41
namespace Akonadi {

42 43
struct ProtocolHelperValuePool
{
Guy Maurel's avatar
Guy Maurel committed
44 45
    typedef Internal::SharedValuePool<QByteArray, QVector> FlagPool;
    typedef Internal::SharedValuePool<QString, QVector> MimeTypePool;
46

Guy Maurel's avatar
Guy Maurel committed
47 48 49
    FlagPool flagPool;
    MimeTypePool mimeTypePool;
    QHash<Collection::Id, Collection> ancestorCollections;
50
};
51

52 53 54 55 56 57
/**
  @internal
  Helper methods for converting between libakonadi objects and their protocol
  representation.

  @todo Add unit tests for this.
58
  @todo Use exceptions for a useful error handling
59 60 61
*/
class ProtocolHelper
{
Guy Maurel's avatar
Guy Maurel committed
62
public:
63 64
    /** Part namespaces. */
    enum PartNamespace {
Guy Maurel's avatar
Guy Maurel committed
65 66 67
        PartGlobal,
        PartPayload,
        PartAttribute
68 69
    };

70 71
    /**
      Parse a cache policy definition.
72
      @param policy The parsed cache policy.
73
      @returns Akonadi::CachePolicy
74
    */
75
    static CachePolicy parseCachePolicy(const Protocol::CachePolicy &policy);
76 77 78 79

    /**
      Convert a cache policy object into its protocol representation.
    */
80
    static Protocol::CachePolicy cachePolicyToProtocol(const CachePolicy &policy);
81

82 83 84
    /**
      Convert a ancestor chain from its protocol representation into an Entity object.
    */
85
    static void parseAncestors(const QVector<Protocol::Ancestor> &ancestors, Entity *entity);
86

87 88 89 90 91 92
    /**
      Convert a ancestor chain from its protocol representation into an Entity object.

      This method allows to pass a @p valuePool which acts as cache, so ancestor paths for the
      same @p parentCollection don't have to be parsed twice.
    */
93 94 95 96
    static void parseAncestorsCached(const QVector<Protocol::Ancestor> &ancestors,
                                     Entity *entity,
                                     Collection::Id parentCollection,
                                     ProtocolHelperValuePool *valuePool = 0);
97

98 99 100
    /**
      Parse a collection description.
      @param data The input data.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
101
      @param requireParent Whether or not we require a parent as part of the data.
102
      @returns The parsed collection
103
    */
104 105 106 107 108 109
    static Collection parseCollection(const Protocol::FetchCollectionsResponse &data, bool requireParent = true);

    static void parseAttributes(const Protocol::Attributes &attributes, Entity *entity);
    static void parseAttributes(const Protocol::Attributes &attributes, AttributeEntity *entity);

    static CollectionStatistics parseCollectionStatistics(const Protocol::FetchCollectionStatsResponse &stats);
110

111 112 113
    /**
      Convert attributes to their protocol representation.
    */
114 115
    static Protocol::Attributes attributesToProtocol(const Entity &entity, bool ns = false);
    static Protocol::Attributes attributesToProtocol(const AttributeEntity &entity, bool ns = false);
116 117 118 119

    /**
      Encodes part label and namespace.
    */
120
    static QByteArray encodePartIdentifier(PartNamespace ns, const QByteArray &label);
121

122 123 124
    /**
      Decode part label and namespace.
    */
Guy Maurel's avatar
Guy Maurel committed
125
    static QByteArray decodePartIdentifier(const QByteArray &data, PartNamespace &ns);
126 127 128 129 130

    /**
      Converts the given set of items into a protocol representation.
      @throws A Akonadi::Exception if the item set contains items with missing/invalid identifiers.
    */
131 132
    template<typename T, template<typename> class Container>
    static Scope entitySetToScope(const Container<T> &_objects)
133
    {
Guy Maurel's avatar
Guy Maurel committed
134 135
        if (_objects.isEmpty()) {
            throw Exception("No objects specified");
136
        }
Guy Maurel's avatar
Guy Maurel committed
137

138
        Container<T> objects(_objects);
Guy Maurel's avatar
Guy Maurel committed
139 140 141 142

        std::sort(objects.begin(), objects.end(), boost::bind(&T::id, _1) < boost::bind(&T::id, _2));
        if (objects.first().isValid()) {
            QVector<typename T::Id>  uids;
143 144
            uids.reserve(objects.size());
            for (const T &object : objects) {
Guy Maurel's avatar
Guy Maurel committed
145 146 147 148
                uids << object.id();
            }
            ImapSet set;
            set.add(uids);
149
            return Scope(set);
Guy Maurel's avatar
Guy Maurel committed
150 151 152 153 154 155 156 157 158 159 160 161
        }

        // check if all items have a remote id
        if (std::find_if(objects.constBegin(), objects.constEnd(),
                         boost::bind(&QString::isEmpty, boost::bind(&T::remoteId, _1)))
            != objects.constEnd()) {
            throw Exception("No remote identifier specified");
        }

        // check if we have RIDs or HRIDs
        if (std::find_if(objects.constBegin(), objects.constEnd(),
                         !boost::bind(static_cast<bool (*)(const T &)>(&CollectionUtils::hasValidHierarchicalRID), _1))
162
                == objects.constEnd() && objects.size() == 1) {  // ### HRID sets are not yet specified
163
            return hierarchicalRidToScope(objects.first());
Guy Maurel's avatar
Guy Maurel committed
164 165 166
        }

        // RIDs
167 168 169 170
        QStringList rids;
        rids.reserve(objects.size());
        for (const T &object : objects) {
            rids << object.remoteId();
Guy Maurel's avatar
Guy Maurel committed
171 172
        }

173
        return Scope(Scope::Rid, rids);
174
    }
175

176 177
    static Scope entitySetToScope(const Tag::List &tags);

178
    static Protocol::ScopeContext commandContextToProtocol(const Akonadi::Collection &collection, const Akonadi::Tag &tag,
179
                                                           const Item::List &requestedItems);
180

Volker Krause's avatar
Volker Krause committed
181 182 183 184 185
    /**
      Converts the given object identifier into a protocol representation.
      @throws A Akonadi::Exception if the item set contains items with missing/invalid identifiers.
    */
    template <typename T>
186
    static Scope entityToScope(const T &object)
Volker Krause's avatar
Volker Krause committed
187
    {
188
        return entitySetToScope(QVector<T>() << object);
Volker Krause's avatar
Volker Krause committed
189 190
    }

191 192 193 194
    /**
      Converts the given collection's hierarchical RID into a protocol representation.
      Assumes @p col has a valid hierarchical RID, so check that before!
    */
195
    static Scope hierarchicalRidToScope(const Collection &col);
196

Volker Krause's avatar
Volker Krause committed
197 198 199 200
    /**
      Converts the HRID of the given item into an ASAP protocol representation.
      Assumes @p item has a valid HRID.
    */
201
    static Scope hierarchicalRidToScope(const Item &item);
Volker Krause's avatar
Volker Krause committed
202

203 204 205
    /**
      Converts a given ItemFetchScope object into a protocol representation.
    */
206
    static Protocol::FetchScope itemFetchScopeToProtocol(const ItemFetchScope &fetchScope);
207

Christian Mollekopf's avatar
Christian Mollekopf committed
208 209 210
    /**
      Converts a given TagFetchScope object into a protocol representation.
    */
211
    static QVector<QByteArray> tagFetchScopeToProtocol(const TagFetchScope &fetchScope);
Christian Mollekopf's avatar
Christian Mollekopf committed
212

213 214 215
    /**
      Parses a single line from an item fetch job result into an Item object.
     */
216 217 218
    static Item parseItemFetchResult(const Protocol::FetchItemsResponse &data, ProtocolHelperValuePool *valuePool = 0);
    static Tag parseTagFetchResult(const Protocol::FetchTagsResponse &data);
    static Relation parseRelationFetchResult(const Protocol::FetchRelationsResponse &data);
Christian Mollekopf's avatar
Christian Mollekopf committed
219

220 221 222
    static QString akonadiStoragePath();
    static QString absolutePayloadFilePath(const QString &fileName);

223
    static bool streamPayloadToFile(const QString &file, const QByteArray &data, QByteArray &error);
224

225
    static Akonadi::Tristate listPreference(const Collection::ListPreference pref);
226 227 228 229 230
};

}

#endif