• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
  • xml
xmldocument.cpp
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#include "xmldocument.h"
21#include "format_p.h"
22#include "xmlreader.h"
23
24#include <KDebug>
25#include <KGlobal>
26#include <KLocalizedString>
27#include <KStandardDirs>
28
29#include <qdom.h>
30#include <qfile.h>
31
32#ifdef HAVE_LIBXML2
33#include <libxml/parser.h>
34#include <libxml/xmlIO.h>
35#include <libxml/xmlschemas.h>
36#endif
37
38static const KCatalogLoader loader( QLatin1String( "libakonadi-xml") );
39
40using namespace Akonadi;
41
42// helper class for dealing with libxml resource management
43template <typename T, void FreeFunc(T)> class XmlPtr
44{
45 public:
46 XmlPtr( const T &t ) : p( t ) {}
47
48 ~XmlPtr()
49 {
50 FreeFunc( p );
51 }
52
53 operator T() const
54 {
55 return p;
56 }
57
58 operator bool() const
59 {
60 return p != 0;
61 }
62
63 private:
64 T p;
65};
66
67static QDomElement findElementByRidHelper( const QDomElement &elem, const QString &rid, const QString &elemName )
68{
69 if ( elem.isNull() )
70 return QDomElement();
71 if ( elem.tagName() == elemName && elem.attribute( Format::Attr::remoteId() ) == rid )
72 return elem;
73 const QDomNodeList children = elem.childNodes();
74 for ( int i = 0; i < children.count(); ++i ) {
75 const QDomElement child = children.at( i ).toElement();
76 if ( child.isNull() )
77 continue;
78 const QDomElement rv = findElementByRidHelper( child, rid, elemName );
79 if ( !rv.isNull() )
80 return rv;
81 }
82 return QDomElement();
83}
84
85namespace Akonadi {
86
87class XmlDocumentPrivate
88{
89 public:
90 XmlDocumentPrivate() :
91 valid( false )
92 {
93 lastError = i18n( "No data loaded." );
94 }
95
96 QDomElement findElementByRid( const QString &rid, const QString &elemName ) const
97 {
98 return findElementByRidHelper( document.documentElement(), rid, elemName );
99 }
100
101 QDomDocument document;
102 QString lastError;
103 bool valid;
104};
105
106}
107
108XmlDocument::XmlDocument() :
109 d( new XmlDocumentPrivate )
110{
111 const QDomElement rootElem = d->document.createElement( Format::Tag::root() );
112 d->document.appendChild( rootElem );
113}
114
115XmlDocument::XmlDocument(const QString& fileName) :
116 d( new XmlDocumentPrivate )
117{
118 loadFile( fileName );
119}
120
121XmlDocument::~XmlDocument()
122{
123 delete d;
124}
125
126bool Akonadi::XmlDocument::loadFile(const QString& fileName)
127{
128 d->valid = false;
129 d->document = QDomDocument();
130
131 if ( fileName.isEmpty() ) {
132 d->lastError = i18n( "No filename specified" );
133 return false;
134 }
135
136 QFile file( fileName );
137 QByteArray data;
138 if ( file.exists() ) {
139 if ( !file.open( QIODevice::ReadOnly ) ) {
140 d->lastError = i18n( "Unable to open data file '%1'.", fileName );
141 return false;
142 }
143 data = file.readAll();
144 } else {
145 d->lastError = i18n( "File %1 does not exist.", fileName );
146 return false;
147 }
148
149#ifdef HAVE_LIBXML2
150 // schema validation
151 XmlPtr<xmlDocPtr, xmlFreeDoc> sourceDoc( xmlParseMemory( data.constData(), data.length() ) );
152 if ( !sourceDoc ) {
153 d->lastError = i18n( "Unable to parse data file '%1'.", fileName );
154 return false;
155 }
156
157 const QString &schemaFileName = KGlobal::dirs()->findResource( "data", QLatin1String("akonadi/akonadi-xml.xsd") );
158 XmlPtr<xmlDocPtr, xmlFreeDoc> schemaDoc( xmlReadFile( schemaFileName.toLocal8Bit(), 0, XML_PARSE_NONET ) );
159 if ( !schemaDoc ) {
160 d->lastError = i18n( "Schema definition could not be loaded and parsed." );
161 return false;
162 }
163 XmlPtr<xmlSchemaParserCtxtPtr, xmlSchemaFreeParserCtxt> parserContext( xmlSchemaNewDocParserCtxt( schemaDoc ) );
164 if ( !parserContext ) {
165 d->lastError = i18n( "Unable to create schema parser context." );
166 return false;
167 }
168 XmlPtr<xmlSchemaPtr, xmlSchemaFree> schema( xmlSchemaParse( parserContext ) );
169 if ( !schema ) {
170 d->lastError = i18n( "Unable to create schema." );
171 return false;
172 }
173 XmlPtr<xmlSchemaValidCtxtPtr, xmlSchemaFreeValidCtxt> validationContext( xmlSchemaNewValidCtxt( schema ) );
174 if ( !validationContext ) {
175 d->lastError = i18n( "Unable to create schema validation context." );
176 return false;
177 }
178
179 if ( xmlSchemaValidateDoc( validationContext, sourceDoc ) != 0 ) {
180 d->lastError = i18n( "Invalid file format." );
181 return false;
182 }
183#endif
184
185 // DOM loading
186 QString errMsg;
187 if ( !d->document.setContent( data, true, &errMsg ) ) {
188 d->lastError = i18n( "Unable to parse data file: %1", errMsg );
189 return false;
190 }
191
192 d->valid = true;
193 d->lastError.clear();
194 return true;
195}
196
197bool XmlDocument::writeToFile(const QString& fileName) const
198{
199 QFile f( fileName );
200 if ( !f.open( QFile::WriteOnly ) ) {
201 d->lastError = f.errorString();
202 return false;
203 }
204
205 f.write( d->document.toByteArray( 2 ) );
206
207 d->lastError.clear();
208 return true;
209}
210
211bool XmlDocument::isValid() const
212{
213 return d->valid;
214}
215
216QString XmlDocument::lastError() const
217{
218 return d->lastError;
219}
220
221QDomDocument& XmlDocument::document() const
222{
223 return d->document;
224}
225
226QDomElement XmlDocument::collectionElementByRemoteId(const QString& rid) const
227{
228 return d->findElementByRid( rid, Format::Tag::collection() );
229}
230
231QDomElement XmlDocument::collectionElement( const Collection &collection ) const
232{
233 if ( collection == Collection::root() )
234 return d->document.documentElement();
235 if ( collection.remoteId().isEmpty() )
236 return QDomElement();
237 if ( collection.parentCollection().remoteId().isEmpty() && collection.parentCollection() != Collection::root() )
238 return d->findElementByRid( collection.remoteId(), Format::Tag::collection() );
239 QDomElement parent = collectionElement( collection.parentCollection() );
240 if ( parent.isNull() )
241 return QDomElement();
242 const QDomNodeList children = parent.childNodes();
243 for ( int i = 0; i < children.count(); ++i ) {
244 const QDomElement child = children.at( i ).toElement();
245 if ( child.isNull() )
246 continue;
247 if ( child.tagName() == Format::Tag::collection() && child.attribute( Format::Attr::remoteId() ) == collection.remoteId() )
248 return child;
249 }
250 return QDomElement();
251}
252
253QDomElement XmlDocument::itemElementByRemoteId(const QString& rid) const
254{
255 return d->findElementByRid( rid, Format::Tag::item() );
256}
257
258Collection XmlDocument::collectionByRemoteId(const QString& rid) const
259{
260 const QDomElement elem = collectionElementByRemoteId( rid );
261 return XmlReader::elementToCollection( elem );
262}
263
264Item XmlDocument::itemByRemoteId(const QString& rid, bool includePayload) const
265{
266 return XmlReader::elementToItem( itemElementByRemoteId( rid ), includePayload );
267}
268
269Collection::List XmlDocument::collections() const
270{
271 return XmlReader::readCollections( d->document.documentElement() );
272}
273
274Tag::List XmlDocument::tags() const
275{
276 return XmlReader::readTags( d->document.documentElement() );
277}
278
279Collection::List XmlDocument::childCollections(const QString& parentCollectionRid) const
280{
281 Collection c;
282 c.setRemoteId( parentCollectionRid );
283 return childCollections( c );
284}
285
286Collection::List XmlDocument::childCollections( const Collection &parentCollection ) const
287{
288 QDomElement parentElem = collectionElement( parentCollection );
289
290 if ( parentElem.isNull() ) {
291 d->lastError = QLatin1String( "Parent node not found." );
292 return Collection::List();
293 }
294
295 Collection::List rv;
296 const QDomNodeList children = parentElem.childNodes();
297 for ( int i = 0; i < children.count(); ++i ) {
298 const QDomElement childElem = children.at( i ).toElement();
299 if ( childElem.isNull() || childElem.tagName() != Format::Tag::collection() )
300 continue;
301 Collection c = XmlReader::elementToCollection( childElem );
302 c.setParentCollection( parentCollection );
303 rv.append( c );
304 }
305
306 return rv;
307}
308
309
310Item::List XmlDocument::items(const Akonadi::Collection& collection, bool includePayload) const
311{
312 const QDomElement colElem = collectionElement( collection );
313 if ( colElem.isNull() ) {
314 d->lastError = i18n( "Unable to find collection %1", collection.name() );
315 return Item::List();
316 } else {
317 d->lastError.clear();
318 }
319
320 Item::List items;
321 const QDomNodeList children = colElem.childNodes();
322 for ( int i = 0; i < children.count(); ++i ) {
323 const QDomElement itemElem = children.at( i ).toElement();
324 if ( itemElem.isNull() || itemElem.tagName() != Format::Tag::item() )
325 continue;
326 items += XmlReader::elementToItem( itemElem, includePayload );
327 }
328
329 return items;
330}
Akonadi::Collection
Represents a collection of PIM items.
Definition collection.h:76
Akonadi::Collection::root
static Collection root()
Returns the root collection.
Definition collection.cpp:192
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition collection.h:81
Akonadi::Entity::setParentCollection
void setParentCollection(const Collection &parent)
Set the parent collection of this object.
Definition entity.cpp:194
Akonadi::Entity::setRemoteId
void setRemoteId(const QString &id)
Sets the remote id of the entity.
Definition entity.cpp:77
Akonadi::XmlDocument::document
QDomDocument & document() const
Returns the DOM document for this XML document.
Definition xmldocument.cpp:221
Akonadi::XmlDocument::collectionByRemoteId
Collection collectionByRemoteId(const QString &rid) const
Returns the collection with the given remote id.
Definition xmldocument.cpp:258
Akonadi::XmlDocument::items
Item::List items(const Collection &collection, bool includePayload=true) const
Returns the items in the given collection.
Definition xmldocument.cpp:310
Akonadi::XmlDocument::tags
Tag::List tags() const
Returns the tags defined in this document.
Definition xmldocument.cpp:274
Akonadi::XmlDocument::isValid
bool isValid() const
Returns true if the document could be parsed successfully.
Definition xmldocument.cpp:211
Akonadi::XmlDocument::XmlDocument
XmlDocument()
Creates an empty document.
Definition xmldocument.cpp:108
Akonadi::XmlDocument::itemElementByRemoteId
QDomElement itemElementByRemoteId(const QString &rid) const
Returns the DOM element representing the item with the given remote id.
Definition xmldocument.cpp:253
Akonadi::XmlDocument::itemByRemoteId
Item itemByRemoteId(const QString &rid, bool includePayload=true) const
Returns the item with the given remote id.
Definition xmldocument.cpp:264
Akonadi::XmlDocument::collectionElementByRemoteId
QDomElement collectionElementByRemoteId(const QString &rid) const
Returns the DOM element representing the collection with the given remote id.
Definition xmldocument.cpp:226
Akonadi::XmlDocument::loadFile
bool loadFile(const QString &fileName)
Parses the given XML file and validates it.
Definition xmldocument.cpp:126
Akonadi::XmlDocument::collections
Collection::List collections() const
Returns the collections defined in this document.
Definition xmldocument.cpp:269
Akonadi::XmlDocument::writeToFile
bool writeToFile(const QString &fileName) const
Writes the current document into the given file.
Definition xmldocument.cpp:197
Akonadi::XmlDocument::collectionElement
QDomElement collectionElement(const Collection &collection) const
Returns the DOM element representing collection.
Definition xmldocument.cpp:231
Akonadi::XmlDocument::childCollections
Collection::List childCollections(const QString &parentCollectionRid) const
Returns immediate child collections of the specified parent collection.
Definition xmldocument.cpp:279
Akonadi::XmlDocument::lastError
QString lastError() const
Returns the last error occurred during file loading/parsing.
Definition xmldocument.cpp:216
Akonadi::XmlReader::elementToItem
AKONADI_XML_EXPORT Item elementToItem(const QDomElement &elem, bool includePayload=true)
Converts an item element.
Definition xmlreader.cpp:128
Akonadi::XmlReader::elementToCollection
AKONADI_XML_EXPORT Collection elementToCollection(const QDomElement &elem)
Converts a collection element.
Definition xmlreader.cpp:54
Akonadi::XmlReader::readCollections
AKONADI_XML_EXPORT Collection::List readCollections(const QDomElement &elem)
Reads recursively all collections starting from the given DOM element.
Definition xmlreader.cpp:72
Akonadi::XmlReader::readTags
AKONADI_XML_EXPORT Tag::List readTags(const QDomElement &elem)
Reads recursively all tags starting from the given DOM element.
Definition xmlreader.cpp:111
Akonadi
FreeBusyManager::Singleton.
Definition actionstatemanager_p.h:28
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal