1 | /* |
2 | Copyright (c) 2009 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #ifndef XMLOPERATIONS_H |
21 | #define XMLOPERATIONS_H |
22 | |
23 | #include <akonadi/collection.h> |
24 | #include <akonadi/item.h> |
25 | #include <akonadi/xml/xmldocument.h> |
26 | |
27 | #include <QtCore/QMetaEnum> |
28 | #include <QtCore/QObject> |
29 | #include <QtCore/QTextStream> |
30 | |
31 | #include <boost/bind.hpp> |
32 | #include <algorithm> |
33 | |
34 | |
35 | /** |
36 | Compares a Akonadi collection sub-tree with reference data supplied in an XML file. |
37 | */ |
38 | class XmlOperations : public QObject |
39 | { |
40 | Q_OBJECT |
41 | Q_ENUMS( CollectionField ItemField ) |
42 | |
43 | public: |
44 | explicit XmlOperations( QObject *parent = 0 ); |
45 | ~XmlOperations(); |
46 | |
47 | enum CollectionField { |
48 | None = 0, |
49 | RemoteId = 1, |
50 | Name = 2, |
51 | ContentMimeType = 4, |
52 | Attributes = 8 |
53 | }; |
54 | |
55 | enum ItemField { |
56 | ItemNone = 0, |
57 | ItemRemoteId = 1, |
58 | ItemMimeType = 2, |
59 | ItemFlags = 4, |
60 | ItemPayload = 8 |
61 | }; |
62 | |
63 | Q_DECLARE_FLAGS( CollectionFields, CollectionField ) |
64 | Q_DECLARE_FLAGS( ItemFields, ItemField ) |
65 | |
66 | void setCollectionKey( CollectionField field ); |
67 | void ignoreCollectionField( CollectionField field ); |
68 | void setItemKey( ItemField field ); |
69 | void ignoreItemField( ItemField field ); |
70 | |
71 | public slots: |
72 | void setRootCollections( const QString &resourceId ); |
73 | void setRootCollections( const Akonadi::Collection::List &roots ); |
74 | void setXmlFile( const QString &fileName ); |
75 | |
76 | Akonadi::Item getItemByRemoteId(const QString& rid); |
77 | Akonadi::Collection getCollectionByRemoteId(const QString& rid); |
78 | |
79 | void setCollectionKey( const QString &fieldName ); |
80 | void ignoreCollectionField( const QString &fieldName ); |
81 | void setItemKey( const QString &fieldName ); |
82 | void ignoreItemField( const QString &fieldName ); |
83 | |
84 | void setNormalizeRemoteIds( bool enable ); |
85 | |
86 | bool compare(); |
87 | void assertEqual(); |
88 | |
89 | QString lastError() const; |
90 | |
91 | bool compareCollections( const Akonadi::Collection::List &cols, const Akonadi::Collection::List &refCols ); |
92 | bool compareCollection( const Akonadi::Collection &col, const Akonadi::Collection &refCol ); |
93 | bool compareItems( const Akonadi::Item::List &items, const Akonadi::Item::List &refItems ); |
94 | bool compareItem( const Akonadi::Item &item, const Akonadi::Item &refItem ); |
95 | bool compareAttributes( const Akonadi::Entity &entity, const Akonadi::Entity &refEntity ); |
96 | bool hasItem(const Akonadi::Item& _item, const Akonadi::Collection& _col); |
97 | bool hasItem(const Akonadi::Item& _item, const QString& rid); |
98 | |
99 | private: |
100 | template <typename T, typename P> |
101 | bool compareValue( const Akonadi::Collection &col, const Akonadi::Collection &refCol, |
102 | T (P::*property)() const, CollectionField propertyType ); |
103 | template <typename T, typename P> |
104 | bool compareValue( const Akonadi::Item& item, const Akonadi::Item& refItem, |
105 | T (P::*property)() const, ItemField propertyType ); |
106 | template <typename T> bool compareValue( const T& value, const T& refValue ); |
107 | |
108 | template <typename T, typename E, typename P> |
109 | void sortEntityList( QList<E> &list, T ( P::*property)() const ) const; |
110 | |
111 | |
112 | Akonadi::Collection normalizeCollection( const Akonadi::Collection &in ) const; |
113 | Akonadi::Item normalizeItem( const Akonadi::Item &in ) const; |
114 | |
115 | private: |
116 | Akonadi::Collection::List mRoots; |
117 | Akonadi::XmlDocument mDocument; |
118 | QString mFileName; |
119 | QString mErrorMsg; |
120 | CollectionFields mCollectionFields; |
121 | CollectionField mCollectionKey; |
122 | ItemFields mItemFields; |
123 | ItemField mItemKey; |
124 | bool mNormalizeRemoteIds; |
125 | }; |
126 | |
127 | |
128 | template <typename T, typename P> |
129 | bool XmlOperations::compareValue( const Akonadi::Collection& col, const Akonadi::Collection& refCol, |
130 | T (P::*property)() const, |
131 | CollectionField propertyType ) |
132 | { |
133 | if ( mCollectionFields & propertyType ) { |
134 | const bool result = compareValue<T>( ((col).*(property))(), ((refCol).*(property))() ); |
135 | if ( !result ) { |
136 | const QMetaEnum me = metaObject()->enumerator( metaObject()->indexOfEnumerator( "CollectionField" ) ); |
137 | mErrorMsg.prepend( QString::fromLatin1( "Collection with remote id '%1' differs in property '%2':\n" ) |
138 | .arg( col.remoteId() ).arg( me.valueToKey( propertyType ) ) ); |
139 | } |
140 | return result; |
141 | } |
142 | return true; |
143 | } |
144 | |
145 | template <typename T, typename P> |
146 | bool XmlOperations::compareValue( const Akonadi::Item& item, const Akonadi::Item& refItem, |
147 | T (P::*property)() const, |
148 | ItemField propertyType ) |
149 | { |
150 | if ( mItemFields & propertyType ) { |
151 | const bool result = compareValue<T>( ((item).*(property))(), ((refItem).*(property))() ); |
152 | if ( !result ) { |
153 | const QMetaEnum me = metaObject()->enumerator( metaObject()->indexOfEnumerator( "ItemField" ) ); |
154 | mErrorMsg.prepend( QString::fromLatin1( "Item with remote id '%1' differs in property '%2':\n" ) |
155 | .arg( item.remoteId() ).arg( me.valueToKey( propertyType ) ) ); |
156 | } |
157 | return result; |
158 | } |
159 | return true; |
160 | } |
161 | |
162 | template <typename T> |
163 | bool XmlOperations::compareValue(const T& value, const T& refValue ) |
164 | { |
165 | if ( value == refValue ) |
166 | return true; |
167 | QTextStream ts( &mErrorMsg ); |
168 | ts << " Actual: " << value << endl << " Expected: " << refValue; |
169 | return false; |
170 | } |
171 | |
172 | template <typename T, typename E, typename P> |
173 | void XmlOperations::sortEntityList( QList<E> &list, T ( P::*property)() const ) const |
174 | { |
175 | std::sort( list.begin(), list.end(), boost::bind( property, _1 ) < boost::bind( property, _2 ) ); |
176 | } |
177 | |
178 | |
179 | #endif |
180 | |