Git commit 85a2d096258e7f4f9de5f02941d9e05d037e0843 by Frank Osterfeld. Committed on 24/02/2012 at 16:39. Pushed by osterfeld into branch 'akregator_port'. Make RssItemSerializer private to the serializer plugin M +35 -1 plugins/CMakeLists.txt M +1 -1 plugins/akonadi_serializer_rss.h A +49 -0 plugins/krss.proto A +49 -0 plugins/rssitemserializer.h [License: LGPL (v2+)] A +182 -0 plugins/rssitemserializer_json.cpp [License: LGPL (v2+)] A +201 -0 plugins/rssitemserializer_protobuf.cpp [License: LGPL (v= 2+)] A +166 -0 plugins/rssitemserializer_qdatastream.cpp [License: LGPL= (v2+)] A +447 -0 plugins/rssitemserializer_xml.cpp [License: LGPL (v2+)] A +52 -0 plugins/tests/CMakeLists.txt A +198 -0 plugins/tests/testxmlitemserializer.cpp [License: LGPL (= v2+)] A +44 -0 plugins/tests/testxmlitemserializer.h [License: LGPL (v2= +)] http://commits.kde.org/kdepim-runtime/85a2d096258e7f4f9de5f02941d9e05d037e0= 843 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f807908..84f432d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,9 +1,43 @@ +add_subdirectory( tests ) + set(akonadi_serializer_rss_SRCS akonadi_serializer_rss.cpp ) = +if(KRSS_ENABLE_PROTOBUF_SERIALIZER) + WRAP_PROTO(krss_LIB_PROTOBUF_SRCS krss.proto) + + set(akonadi_serializer_rss_SRCS + ${akonadi_serializer_rss_SRCS} + ${krss_LIB_PROTOBUF_SRCS} + rssitemserializer_protobuf.cpp + ) + set(KRSS_EXTRA_LIBS ${PROTOBUF_LIBRARY}) +else(KRSS_ENABLE_PROTOBUF_SERIALIZER) +if(KRSS_ENABLE_QDATASTREAM_SERIALIZER) + set(akonadi_serializer_rss_SRCS + ${akonadi_serializer_rss_SRCS} + rssitemserializer_qdatastream.cpp + ) + set(KRSS_EXTRA_LIBS ${PROTOBUF_LIBRARY}) +else(KRSS_ENABLE_QDATASTREAM_SERIALIZER) +if(KRSS_ENABLE_JSON_SERIALIZER) + set(akonadi_serializer_rss_SRCS + ${akonadi_serializer_rss_SRCS} + rssitemserializer_json.cpp + ) + set(KRSS_EXTRA_LIBS qjson) +else(KRSS_ENABLE_JSON_SERIALIZER) + set(akonadi_serializer_rss_SRCS + ${akonadi_serializer_rss_SRCS} + rssitemserializer_xml.cpp + ) +endif(KRSS_ENABLE_JSON_SERIALIZER) +endif(KRSS_ENABLE_QDATASTREAM_SERIALIZER) +endif(KRSS_ENABLE_PROTOBUF_SERIALIZER) + kde4_add_plugin(akonadi_serializer_rss ${akonadi_serializer_rss_SRCS}) -target_link_libraries(akonadi_serializer_rss ${KDE4_KIO_LIBS} ${KDEPIMLIBS= _AKONADI_LIBS} krss) +target_link_libraries(akonadi_serializer_rss ${KDE4_KIO_LIBS} ${KDEPIMLIBS= _AKONADI_LIBS} ${KDEPIMLIBS_SYNDICATION_LIBS} krss) = install(TARGETS akonadi_serializer_rss DESTINATION ${PLUGIN_INSTALL_DIR}) install(FILES akonadi_serializer_rss.desktop DESTINATION "${DATA_INSTALL_D= IR}/akonadi/plugins/serializer") diff --git a/plugins/akonadi_serializer_rss.h b/plugins/akonadi_serializer_= rss.h index ce8a863..9089c29 100644 --- a/plugins/akonadi_serializer_rss.h +++ b/plugins/akonadi_serializer_rss.h @@ -18,7 +18,7 @@ #ifndef AKONADI_SERIALIZER_RSS #define AKONADI_SERIALIZER_RSS = -#include +#include "rssitemserializer.h" = #include = diff --git a/plugins/krss.proto b/plugins/krss.proto new file mode 100644 index 0000000..4837532 --- /dev/null +++ b/plugins/krss.proto @@ -0,0 +1,49 @@ +package KRss.Protobuf; + + +message ItemHeader { + repeated string tags =3D 1; + required int32 hash =3D 2; + required bool guidIsHash =3D 3; + required string guid =3D 4; + required string title =3D 5; + required string link =3D 6; + required int64 datePublished =3D 7; + required int64 dateUpdated =3D 8; + required string language =3D 9; + repeated Person authors =3D 10; + repeated Enclosure enclosures =3D 11; + repeated Category categories =3D 12; + required int32 commentsCount =3D 13; + required string commentsLink =3D 14; + required string commentsFeed =3D 15; + required string commentPostUri =3D 16; + repeated string additionalProperties =3D 17; +} + +message ItemContent { + required string description =3D 1; + required string content =3D 2; = +} + +message Person { + required string name =3D 1; + required string email =3D 2; + required string uri =3D 3; +} + +message Enclosure { + required string url =3D 1; + required string title =3D 2; + required string type =3D 3; + required uint32 length =3D 4; + required uint32 duration =3D 5; = +} + +message Category { + required string label =3D 1; + required string scheme =3D 2; + required string term =3D 3; +} + + diff --git a/plugins/rssitemserializer.h b/plugins/rssitemserializer.h new file mode 100644 index 0000000..7dcaaed --- /dev/null +++ b/plugins/rssitemserializer.h @@ -0,0 +1,49 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2007 Frank Osterfeld + * + * 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 Licen= se + * 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. + * + */ + +#ifndef KRSS_RSSITEMSERIALIZER_H +#define KRSS_RSSITEMSERIALIZER_H + +class QByteArray; + +namespace KRss +{ + +class RssItem; + +class RssItemSerializer +{ +public: + + enum ItemPart { + Headers=3D0x01, + Content=3D0x02, + Full=3DHeaders|Content + }; + + static void serialize( const KRss::RssItem& item, QByteArray& array, I= temPart part =3D Full ); + static bool deserialize( KRss::RssItem& item, const QByteArray& array,= ItemPart part =3D Full ); +}; + +} + +#endif // KRSS_RSSITEMSERIALIZER_H diff --git a/plugins/rssitemserializer_json.cpp b/plugins/rssitemserializer= _json.cpp new file mode 100644 index 0000000..87dba61 --- /dev/null +++ b/plugins/rssitemserializer_json.cpp @@ -0,0 +1,182 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2009 Frank Osterfeld + * + * 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 Licen= se + * 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 "rssitemserializer.h" +#include "rssitem.h" +#include "category.h" +#include "enclosure.h" +#include "person.h" + +#include +#include +#include + +#include +#include + +using namespace boost; +using namespace KRss; + +static QVariantMap serialize( const Enclosure& e ) { + QVariantMap h; + h.insert( QLatin1String( "duration" ), e.duration() ); + h.insert( QLatin1String( "length" ), e.length() ); + h.insert( QLatin1String( "title" ), e.title() ); + h.insert( QLatin1String( "type" ), e.type() ); + h.insert( QLatin1String( "url" ), e.url() ); + return h; +} + +static QVariantMap serialize( const Person& p ) { + QVariantMap h; + h.insert( QLatin1String( "email" ), p.email() ); + h.insert( QLatin1String( "name" ), p.name() ); + h.insert( QLatin1String( "uri" ), p.uri() ); + return h; +} + +static QVariantMap serialize( const Category& c ) { + QVariantMap h; + h.insert( QLatin1String( "label"), c.label() ); + h.insert( QLatin1String( "scheme" ), c.scheme() ); + h.insert( QLatin1String( "term" ), c.term() ); + return h; +} + +template +static QVariantList doSerialize( const QList& l ) { + QVariantList list; + Q_FOREACH( const T& i, l ) + list.append( serialize( i ) ); = + return list; +} + +static Category deserializeCategory( const QVariantMap& h ) { + Category c; + c.setLabel( h.value( QLatin1String( "label" ) ).toString() ); + c.setScheme( h.value( QLatin1String( "scheme" ) ).toString() ); + c.setTerm( h.value( QLatin1String( "term" ) ).toString() ); + return c; +} + + +static Enclosure deserializeEnclosure( const QVariantMap& h ) { + Enclosure e; + e.setDuration( h.value( QLatin1String( "duration" ) ).toInt() ); + e.setLength( h.value( QLatin1String( "length" ) ).toInt() ); + e.setTitle( h.value( QLatin1String( "title" ) ).toString() ); + e.setType( h.value( QLatin1String( "type" ) ).toString() ); + e.setUrl( h.value( QLatin1String( "url" ) ).toString() ); + return e; +} + + +static Person deserializePerson( const QVariantMap& h ) { + Person p; + p.setEmail( h.value( QLatin1String( "email" ) ).toString() ); + p.setName( h.value( QLatin1String( "name" ) ).toString() ); + p.setUri( h.value( QLatin1String( "uri" ) ).toString() ); + return p; +} + +static QList deserializePersons( const QVariantList& h ) { + QList l; + Q_FOREACH( const QVariant& i, h ) + l.push_back( deserializePerson( i.toMap() ) ); + return l; +} + +static QList deserializeCategories( const QVariantList& h ) { + QList l; + Q_FOREACH( const QVariant& i, h ) + l.push_back( deserializeCategory( i.toMap() ) ); + return l; +} + +static QList deserializeEnclosures( const QVariantList& h ) { + QList l; + Q_FOREACH( const QVariant& i, h ) + l.push_back( deserializeEnclosure( i.toMap() ) ); + return l; +} + +void RssItemSerializer::serialize( const RssItem& item, QByteArray& ba, It= emPart part ) { + QVariantMap hash; + //hash.insert( QLatin1String( "hash" ), QVariant::fromValue( item.hash= () ) ); + hash.insert( QLatin1String( "guidIsHash" ), item.guidIsHash() ); + hash.insert( QLatin1String( "title" ), item.title() ); + hash.insert( QLatin1String( "link" ), item.link() ); + hash.insert( QLatin1String( "description" ), item.description() ); + hash.insert( QLatin1String( "content" ), item.content() ); + hash.insert( QLatin1String( "language" ), item.language() ); + hash.insert( QLatin1String( "datePublished" ), item.datePublished().to= String() ); + hash.insert( QLatin1String( "dateUpdated" ), item.dateUpdated().toStri= ng() ); + hash.insert( QLatin1String( "guid" ), item.guid() ); + hash.insert( QLatin1String( "commentsCount" ), item.commentsCount() ); + hash.insert( QLatin1String( "commentPostUri" ), item.commentPostUri() = ); + hash.insert( QLatin1String( "commentsFeed" ), item.commentsFeed() ); + hash.insert( QLatin1String( "commentsLink" ), item.commentsLink() ); + hash.insert( QLatin1String( "enclosures" ), QVariant( doSerialize( ite= m.enclosures() ) ) ); + hash.insert( QLatin1String( "categories" ), doSerialize( item.categori= es() ) ); + hash.insert( QLatin1String( "authors" ), doSerialize( item.authors() )= ); +#if 0 = + const QHash ap =3D item.customProperties(); + stream << static_cast( ap.size() ); + Q_FOREACH( const QString& key, ap.keys() ) + stream << key << ap.value( key ); +#endif + QJSon::Serializer serializer; + ba =3D serializer.serialize( hash ); + qDebug() << ba; +} + +bool RssItemSerializer::deserialize( RssItem& item, const QByteArray& ba, = ItemPart part ) { + QJSon::Parser parser; + bool ok; + QVariantMap hash =3D parser.parse( ba, &ok ).toMap(); + if ( !ok ) + return false; + //item.setHash( hash.value( QLatin1String( "hash" ) ).value() = ); + item.setGuidIsHash( hash.value( QLatin1String( "guidIsHash" ) ).toBool= () ); + item.setTitle( hash.value( QLatin1String( "title" ) ).toString() ); + item.setLink( hash.value( QLatin1String( "link" ) ).toString() ); + item.setDescription( hash.value( QLatin1String( "description" ) ).toSt= ring() ); + item.setContent( hash.value( QLatin1String( "content" ) ).toString() ); + item.setLanguage( hash.value( QLatin1String( "language" ) ).toString()= ); + item.setDatePublished( KDateTime::fromString( hash.value( QLatin1Strin= g( "datePublished" ) ).toString() ) ); + item.setDateUpdated( KDateTime::fromString( hash.value( QLatin1String(= "dateUpdated" ) ).toString() ) ); + item.setGuid( hash.value( QLatin1String( "guid" ) ).toString() ); + item.setCommentsCount( hash.value( QLatin1String( "commentsCount" ) ).= toInt() ); + item.setCommentPostUri( hash.value( QLatin1String( "commentPostUri" ) = ).toString() ); + item.setCommentsFeed( hash.value( QLatin1String( "commentsFeed" ) ).to= String() ); + item.setCommentsLink( hash.value( QLatin1String( "commentsLink" ) ).to= String() ); + item.setEnclosures( deserializeEnclosures( hash.value( QLatin1String( = "enclosures" ) ).toList() ) ); + item.setCategories( deserializeCategories( hash.value( QLatin1String( = "categories" ) ).toList() ) ); + item.setAuthors( deserializePersons( hash.value( QLatin1String( "autho= rs" ) ).toList() ) ); + return true; +} + +#undef READ +#undef READ2 +#undef READSTRING +#undef READSTRING2 +#undef READDATE diff --git a/plugins/rssitemserializer_protobuf.cpp b/plugins/rssitemserial= izer_protobuf.cpp new file mode 100644 index 0000000..d779a8b --- /dev/null +++ b/plugins/rssitemserializer_protobuf.cpp @@ -0,0 +1,201 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2009 Frank Osterfeld + * + * 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 Licen= se + * 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 "rssitemserializer.h" +#include "rssitem.h" +#include "category.h" +#include "enclosure.h" +#include "person.h" + +#include "krss.pb.h" + +#include + +#include + +#include + +using namespace KRss; +//TODO: in the plugin, do at init time: +// GOOGLE_PROTOBUF_VERIFY_VERSION; +//on plugin destruction, do +//google::protobuf::ShutdownProtobufLibrary(); + + +static Protobuf::Person writePerson( const Person& o ) { + Protobuf::Person r; + r.set_name( o.name().toUtf8().constData() ); + r.set_email( o.email().toUtf8().constData() ); + r.set_uri( o.uri().toUtf8().constData() ); + return r; +} + +static Protobuf::Enclosure writeEnclosure( const Enclosure& o ) { + Protobuf::Enclosure r; + r.set_url( o.url().toUtf8().constData() ); + r.set_title( o.title().toUtf8().constData() ); + r.set_type( o.type().toUtf8().constData() ); + r.set_duration( o.duration() ); + r.set_length( o.length() ); + return r; +} + +static Protobuf::Category writeCategory( const Category& o ) { + Protobuf::Category r; + r.set_label( o.label().toUtf8().constData() ); + r.set_scheme( o.scheme().toUtf8().constData() ); + r.set_term( o.term().toUtf8().constData() ); + return r; +} + +void RssItemSerializer::serialize( const KRss::RssItem& item, QByteArray& = array, ItemPart part ) const +{ + const bool writeHeaders =3D part =3D=3D Full || part =3D=3D Headers; + const bool writeContent =3D part =3D=3D Full || part =3D=3D Content; + + if ( writeHeaders ) { + Protobuf::ItemHeader header; + + header.set_hash( item.hash() ); + header.set_guidishash( item.guidIsHash() ); + header.set_guid( item.guid().toUtf8().constData() ); + header.set_title( item.title().toUtf8().constData() ); + header.set_link( item.link().toUtf8().constData() ); + header.set_datepublished( item.datePublished().toTime_t() ); + header.set_dateupdated( item.dateUpdated().toTime_t() ); + header.set_language( item.language().toUtf8().constData() ); + Q_FOREACH( const Person& i, item.authors() ) + *header.add_authors() =3D writePerson( i ); + Q_FOREACH( const Enclosure& i, item.enclosures() ) + *header.add_enclosures() =3D writeEnclosure( i ); + Q_FOREACH( const Category& i, item.categories() ) + *header.add_categories() =3D writeCategory( i ); + header.set_commentscount( item.commentsCount() ); + header.set_commentslink( item.commentsLink().toUtf8().constData() = ); + header.set_commentsfeed( item.commentsFeed().toUtf8().constData() = ); + header.set_commentposturi( item.commentPostUri().toUtf8().constDat= a() ); + + std::string out; + header.SerializeToString( &out ); + array.append( out.c_str(), out.size() ); + } + + if ( writeContent ) { + Protobuf::ItemContent content; + + content.set_description( item.description().toUtf8().constData() ); + content.set_content( item.content().toUtf8().constData() ); + + std::string out; + content.SerializeToString( &out ); + array.append( out.c_str(), out.size() ); + } +} + +static Enclosure readEnclosure( const Protobuf::Enclosure& pe ) { + Enclosure enc; + enc.setUrl( QString::fromUtf8( pe.url().c_str() ) ); + enc.setTitle( QString::fromUtf8( pe.title().c_str() ) ); + enc.setType( QString::fromUtf8( pe.type().c_str() ) ); + enc.setDuration( pe.duration() ); + enc.setLength( pe.length() ); + return enc; +} + +static Category readCategory( const Protobuf::Category& pc ) { + Category cat; + cat.setLabel( QString::fromUtf8( pc.label().c_str() ) ); + cat.setScheme( QString::fromUtf8( pc.scheme().c_str() ) ); + cat.setTerm( QString::fromUtf8( pc.term().c_str() ) ); + return cat; +} + + +static Person readPerson( const Protobuf::Person& pp ) { + Person p; + p.setName( QString::fromUtf8( pp.name().c_str() ) ); + p.setEmail( QString::fromUtf8( pp.email().c_str() ) ); + p.setUri( QString::fromUtf8( pp.uri().c_str() ) ); + return p; +} + +bool KRss::RssItemSerializer::deserialize( KRss::RssItem& item, const QByt= eArray& array, ItemPart part ) const +{ + const bool readHeaders =3D part =3D=3D Full || part =3D=3D Headers; + const bool readContent =3D part =3D=3D Full || part =3D=3D Content; + + //TODO: these ifs are wrong, the Full case must be handled differently= (FullItem message) + + if ( readHeaders ) { + Protobuf::ItemHeader header; + const bool parsed =3D header.ParsePartialFromArray( array.constDat= a(), array.size() ); + if ( !parsed ) + return false; + item.setHash( header.hash() ); + item.setGuidIsHash( header.guidishash() ); + item.setGuid( QString::fromUtf8( header.guid().c_str() ) ); + item.setTitle( QString::fromUtf8( header.title().c_str() ) ); + item.setLink( QString::fromUtf8( header.link().c_str() ) ); + KDateTime published; + published.setTime_t( header.datepublished() ); + item.setDatePublished( published ); + KDateTime updated; + updated.setTime_t( header.dateupdated() ); + item.setDateUpdated( updated ); + + QList enclosures; + for ( int i =3D 0; i < header.enclosures_size(); ++i ) + enclosures.append( readEnclosure( header.enclosures( i ) ) ); + item.setEnclosures( enclosures ); + + QList categories; + for ( int i =3D 0; i < header.categories_size(); ++i ) + categories.append( readCategory( header.categories( i ) ) ); + item.setCategories( categories ); + + QList authors; + for ( int i =3D 0; i < header.authors_size(); ++i ) + authors.append( readPerson( header.authors( i ) ) ); + item.setAuthors( authors ); + + item.setCommentsCount( header.commentscount() ); + item.setCommentsLink( QString::fromUtf8( header.commentslink().c_s= tr() ) ); + item.setCommentsFeed( QString::fromUtf8( header.commentsfeed().c_s= tr() ) ); + item.setCommentPostUri( QString::fromUtf8( header.commentposturi()= .c_str() ) ); + } + + item.setHeadersLoaded( readHeaders ); + + if ( readContent ) { + Protobuf::ItemContent content; + const bool parsed =3D content.ParsePartialFromArray( array.constDa= ta(), array.size() ); + if ( !parsed ) + return false; + item.setDescription( QString::fromUtf8( content.description().c_st= r() ) ); + item.setContent( QString::fromUtf8( content.content().c_str() ) ); + } + + item.setContentLoaded( readContent ); + + return true; +} + diff --git a/plugins/rssitemserializer_qdatastream.cpp b/plugins/rssitemser= ializer_qdatastream.cpp new file mode 100644 index 0000000..b678056 --- /dev/null +++ b/plugins/rssitemserializer_qdatastream.cpp @@ -0,0 +1,166 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2009 Frank Osterfeld + * + * 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 Licen= se + * 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 "rssitemserializer.h" +#include "rssitem.h" +#include "category.h" +#include "enclosure.h" +#include "person.h" + +#include + +#include + +using namespace KRss; + +void RssItemSerializer::serialize( const RssItem& item, QByteArray& ba, It= emPart part ) { + QDataStream stream( &ba, QIODevice::WriteOnly ); + const bool writeHeaders =3D ( part & Headers ) !=3D 0; + const bool writeContent =3D ( part & Content ) !=3D 0; + + if ( writeHeaders ) { + stream << static_cast( item.hash() ) + << item.guidIsHash() + << item.title() + << item.datePublished().toString() + << item.dateUpdated().toString() + << item.guid(); + stream << static_cast( item.authors().count() ); + Q_FOREACH( const Person& i, item.authors() ) + stream << i.email() << i.name() << i.uri(); + } + if ( writeContent ) { + stream << item.content() + << item.description() + << item.link() + << item.language() + << static_cast( item.commentsCount() ) + << item.commentPostUri() + << item.commentsFeed() + << item.commentsLink(); + stream << static_cast( item.enclosures().count() ); + Q_FOREACH( const Enclosure& i, item.enclosures() ) + stream << static_cast( i.duration() ) << static_cast( i.length() ) << i.title() << i.type() << i.url(); + stream << static_cast( item.categories().count() ); + Q_FOREACH( const Category& i, item.categories() ) + stream << i.label() << i.scheme() << i.term(); + const QHash ap =3D item.customProperties(); + stream << static_cast( ap.size() ); + Q_FOREACH( const QString& key, ap.keys() ) + stream << key << ap.value( key ); + } +} + +#define READSTRING(name) QString name; stream >> name; item.set##name( nam= e ); +#define READSTRING2(name,target) QString name; stream >> name; target.set#= #name( name ); +#define READ(type,name) type name; stream >> name; item.set##name( name ); +#define READ2(type,name,target) type name; stream >> name; target.set##nam= e( name ); +#define READDATE(name) QString name; stream >> name; item.set##name( KDate= Time::fromString( name ) ); + +bool RssItemSerializer::deserialize( RssItem& itemOut, const QByteArray& b= a, ItemPart part ) { + const bool readHeaders =3D ( part & Headers ) !=3D 0; + const bool readContent =3D ( part & Content ) !=3D 0; + + QDataStream stream( ba ); + RssItem item; + if ( readHeaders ) { + READ(qint64,Hash) + READ(bool,GuidIsHash) + READSTRING(Title) + READDATE(DatePublished) + READDATE(DateUpdated) + READSTRING(Guid) + quint32 authorCount; + stream >> authorCount; + QList authors; + for ( quint32 i =3D 0; i < authorCount; ++i ) { + Person auth; + READSTRING2(Email, auth) + READSTRING2(Name, auth) + READSTRING2(Uri, auth) + authors.append( auth ); + } + item.setAuthors( authors ); + } + if ( readContent ) { + READSTRING(Content) + READSTRING(Description) + READSTRING(Link) + + READSTRING(Language) + READ(qint32,CommentsCount) + READSTRING(CommentPostUri) + READSTRING(CommentsFeed) + READSTRING(CommentsLink) + quint32 encCount; + stream >> encCount; + QList enclosures; + for ( quint32 i =3D 0; i < encCount; ++i ) { + Enclosure enc; + READ2(qint32, Duration, enc) + READ2(qint32, Length, enc) + READSTRING2(Title, enc) + READSTRING2(Type, enc) + READSTRING2(Url, enc) + enclosures.append( enc ); + } + item.setEnclosures( enclosures ); + + quint32 catCount =3D 0; + stream >> catCount; + QList categories; + for ( quint32 i =3D 0; i < catCount; ++i ) { + Category cat; + READSTRING2(Label, cat) + READSTRING2(Scheme, cat) + READSTRING2(Term, cat) + categories.append( cat ); + } + item.setCategories( categories ); + + + quint32 apCount; + stream >> apCount; + for ( quint32 i =3D 0; i < apCount; ++i ) { + QString key; + stream >> key; + QString value; + stream >> value; + item.setCustomProperty( key, value ); + } + } + itemOut =3D item; + + if ( readHeaders ) + item.setHeadersLoaded( true ); + + if ( readContent ) + item.setContentLoaded( true ); + + return true; +} + +#undef READ +#undef READ2 +#undef READSTRING +#undef READSTRING2 +#undef READDATE diff --git a/plugins/rssitemserializer_xml.cpp b/plugins/rssitemserializer_= xml.cpp new file mode 100644 index 0000000..e1136da --- /dev/null +++ b/plugins/rssitemserializer_xml.cpp @@ -0,0 +1,447 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2007 Frank Osterfeld + * + * 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 Licen= se + * 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 "rssitemserializer.h" +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace KRss; + +namespace { + +enum TextMode { + PlainText, + Html +}; + +static QString krssNamespace() +{ + return QLatin1String("http://akregator.kde.org/krss#"); +} + +class Element +{ +public: + Element( const QString& ns_, const QString& name_, const QVariant& def= aultValue_ =3D QVariant() ) : ns( ns_ ), name( name_ ), qualifiedName( ns += QLatin1Char(':') + name ), defaultValue( defaultValue_ ) + { + } + + const QString ns; + const QString name; + const QString qualifiedName; + const QVariant defaultValue; + + bool isNextIn( const QXmlStreamReader& reader ) const + { + return reader.isStartElement() && reader.name() =3D=3D name && rea= der.namespaceUri() =3D=3D ns; + } + + void writeStartElement( QXmlStreamWriter& writer ) const + { + if ( !ns.isNull() ) + writer.writeStartElement( ns, name ); + else + writer.writeStartElement( name ); + } + + void write( const QVariant& value , QXmlStreamWriter& writer, TextMode= mode =3D PlainText ) const + { + if ( value =3D=3D defaultValue ) + return; + + if ( ns.isEmpty() ) + writer.writeStartElement( name ); + else + writer.writeStartElement( ns, name ); + if ( mode =3D=3D Html ) + { + writer.writeAttribute( QLatin1String("type"), QLatin1String("h= tml") ); + } + const QVariant qv( value ); + Q_ASSERT( qv.canConvert( QVariant::String ) ); + writer.writeCharacters( qv.toString() ); + writer.writeEndElement(); + } +}; + +struct Elements +{ + Elements() : atomNS( Syndication::Atom::atom1Namespace() ), + krssNS( krssNamespace() ), + commentNS( Syndication::commentApiNamespace() ), + title( atomNS, QLatin1String("title"), QString() ), + summary( atomNS, QLatin1String("summary"), QString() ), + content( atomNS, QLatin1String("content"), QString() ), + link( atomNS, QLatin1String("link"), QString() ), + language( atomNS, QLatin1String("language"), QString() ), + guid( atomNS, QLatin1String("id"), QString() ), + published( atomNS, QLatin1String("published"), KDateTime(= ).toString( KDateTime::ISODate ) ), + updated( atomNS, QLatin1String("updated"), KDateTime().to= String( KDateTime::ISODate ) ), + commentsCount( Syndication::slashNamespace(), QLatin1Stri= ng("comments"), -1 ), + commentsFeed( commentNS, QLatin1String("commentRss"), QSt= ring() ), + commentPostUri( commentNS, QLatin1String("comment"), QStr= ing() ), + commentsLink( krssNS, QLatin1String("commentsLink"), QStr= ing() ), + hash( krssNS, QLatin1String("hash"), 0 ), + guidIsHash( krssNS, QLatin1String("idIsHash"), false ), + sourceFeedId( krssNS, QLatin1String("sourceFeedId"), -1 ), + name( atomNS, QLatin1String("name"), QString() ), + uri( atomNS, QLatin1String("uri"), QString() ), + email( atomNS, QLatin1String("email"), QString() ), + author( atomNS, QLatin1String("author"), QString() ), + category( atomNS, QLatin1String("category"), QString() ), + customProperty( krssNS, QLatin1String("customProperty"), = QString() ), + key( krssNS, QLatin1String("key"), QString() ), + value( krssNS, QLatin1String("value"), QString() ), + entry( atomNS, QLatin1String("entry"), QString() ) +{} + const QString atomNS; + const QString krssNS; + const QString commentNS; + const Element title; + const Element summary; + const Element content; + const Element link; + const Element language; + const Element guid; + const Element published; + const Element updated; + const Element commentsCount; + const Element commentsFeed; + const Element commentPostUri; + const Element commentsLink; + const Element hash; + const Element guidIsHash; + const Element sourceFeedId; + const Element name; + const Element uri; + const Element email; + const Element author; + const Element category; + const Element customProperty; + const Element key; + const Element value; + const Element entry; + static const Elements instance; +}; + +const Elements Elements::instance; + +static void writeAttributeIfNotEmpty( const QString& ns, const QString& el= ement, const QVariant& value, QXmlStreamWriter& writer ) +{ + const QString text =3D value.toString(); + if ( text.isEmpty() ) + return; + writer.writeAttribute( ns, element, text ); +} + +static void writeAttributeIfNotEmpty( const QString& element, const QVaria= nt& value, QXmlStreamWriter& writer ) +{ + const QString text =3D value.toString(); + if ( text.isEmpty() ) + return; + writer.writeAttribute( element, text ); +} + +static void writeLink( const QString& url, QXmlStreamWriter& writer ) +{ + if ( url.isEmpty() ) + return; + Elements::instance.link.writeStartElement( writer ); + writer.writeAttribute( QLatin1String("rel"), QLatin1String("alternate"= ) ); + writeAttributeIfNotEmpty( QLatin1String("href"), url, writer ); + writer.writeEndElement(); +} + +static void writeCategory( const KRss::Category& category, QXmlStreamWrite= r& writer ) +{ + Elements::instance.category.writeStartElement( writer ); + writeAttributeIfNotEmpty( QLatin1String("term"), category.term(), writ= er ); + writeAttributeIfNotEmpty( QLatin1String("scheme"), category.scheme(), = writer ); + writeAttributeIfNotEmpty( QLatin1String("label"), category.label(), wr= iter ); + writer.writeEndElement(); +} + +static void writeAuthor( const KRss::Person& person, QXmlStreamWriter& wri= ter ) +{ + const QString atomNS =3D Syndication::Atom::atom1Namespace(); + Elements::instance.author.writeStartElement( writer ); + Elements::instance.name.write( person.name(), writer ); + Elements::instance.uri.write( person.uri(), writer ); + Elements::instance.email.write( person.email(), writer ); + writer.writeEndElement(); +} + +static void writeEnclosure( const KRss::Enclosure& enclosure, QXmlStreamWr= iter& writer ) +{ + Elements::instance.link.writeStartElement( writer ); + writeAttributeIfNotEmpty( QLatin1String("rel"), QLatin1String("enclosu= re"), writer ); + writeAttributeIfNotEmpty( QLatin1String("href"), enclosure.url(), writ= er ); + writeAttributeIfNotEmpty( QLatin1String("title"), enclosure.title(), w= riter ); + writeAttributeIfNotEmpty( QLatin1String("length"), enclosure.length(),= writer ); + writeAttributeIfNotEmpty( QLatin1String("type"), enclosure.type(), wri= ter ); + const uint duration =3D enclosure.duration(); + if ( duration !=3D 0 ) + writer.writeAttribute( Syndication::itunesNamespace(), QLatin1Stri= ng("duration"), QString::number( duration ) ); + writer.writeEndElement(); +} + +static void writeItemHeaders( const KRss::RssItem& item, QXmlStreamWriter&= writer ) +{ + Elements::instance.title.write( item.title(), writer, Html ); + writeLink( item.link(), writer ); + Elements::instance.guid.write( item.guid(), writer ); + + const KDateTime updated =3D item.dateUpdated(); + const KDateTime published =3D item.datePublished(); + Elements::instance.published.write( published.toString( KDateTime::ISO= Date ), writer ); + if ( updated.isValid() && updated !=3D published ) + Elements::instance.updated.write( updated.toString( KDateTime::ISO= Date ), writer ); + + Q_FOREACH( const KRss::Category& i, item.categories() ) + writeCategory( i, writer ); + + Q_FOREACH( const KRss::Person& i, item.authors() ) + writeAuthor( i, writer ); + + Q_FOREACH( const KRss::Enclosure& i, item.enclosures() ) + writeEnclosure( i, writer ); + + Elements::instance.hash.write( item.hash(), writer ); + Elements::instance.guidIsHash.write( item.guidIsHash(), writer ); + Elements::instance.sourceFeedId.write( item.sourceFeedId(), writer ); + +} + +static void writeItemContent( const KRss::RssItem& item, QXmlStreamWriter&= writer ) +{ + const QString description =3D item.description(); + Elements::instance.summary.write( description, writer, Html ); + const QString content =3D item.content(); + if ( content !=3D description ) + Elements::instance.content.write( content, writer, Html ); + Elements::instance.language.write( item.language(), writer ); + Elements::instance.commentsFeed.write( item.commentsFeed(), writer ); + Elements::instance.commentPostUri.write( item.commentPostUri(), writer= ); + Elements::instance.commentsCount.write( item.commentsCount(), writer ); + Elements::instance.commentsLink.write( item.commentsLink(), writer ); + const QHash props =3D item.customProperties(); + QHash::const_iterator it =3D props.constBegin(); + while ( it !=3D props.constEnd() ) + { + Elements::instance.customProperty.writeStartElement( writer ); + Elements::instance.key.write( it.key(), writer ); + Elements::instance.value.write( it.value(), writer ); + writer.writeEndElement(); + ++it; + } +} + +static void writeItem( const KRss::RssItem& item, QXmlStreamWriter& writer= , KRss::RssItemSerializer::ItemPart part ) +{ + const QString atomNS =3D Syndication::Atom::atom1Namespace(); + const QString commentNS =3D Syndication::commentApiNamespace(); + const QString krssNS =3D krssNamespace(); + writer.writeDefaultNamespace( atomNS ); + writer.writeNamespace( commentNS, QLatin1String("comment") ); + writer.writeNamespace( krssNS, QLatin1String("krss") ); + writer.writeNamespace( Syndication::itunesNamespace(), QLatin1String("= itunes") ); + + Elements::instance.entry.writeStartElement( writer ); + if ( ( part & RssItemSerializer::Headers ) !=3D 0 ) + writeItemHeaders( item, writer ); + if ( ( part & RssItemSerializer::Content ) !=3D 0 ) + writeItemContent( item, writer ); + + writer.writeEndElement(); // Entry +} + +static void readLink( KRss::RssItem& item, QXmlStreamReader& reader ) +{ + const QXmlStreamAttributes attrs =3D reader.attributes(); + const QString rel =3D attrs.value( QString(), QLatin1String("rel") ).t= oString(); + if ( rel =3D=3D QLatin1String("alternate") ) + { + item.setLink( attrs.value( QString(), QLatin1String("href") ).toSt= ring() ); + } + else if ( rel =3D=3D QLatin1String("enclosure") ) + { + KRss::Enclosure enc; + enc.setUrl( attrs.value( QString(), QLatin1String("href") ).toStri= ng() ); + enc.setType( attrs.value( QString(), QLatin1String("type") ).toStr= ing() ); + enc.setTitle( attrs.value( QString(), QLatin1String("title") ).toS= tring() ); + bool ok; + const uint length =3D attrs.value( QString(), QLatin1String("lengt= h") ).toString().toUInt( &ok ); + if ( ok ) + enc.setLength( length ); + const uint duration =3D attrs.value( Syndication::itunesNamespace(= ), QLatin1String("duration") ).toString().toUInt( &ok ); + if ( ok ) + enc.setDuration( duration ); + QList encs =3D item.enclosures(); + encs.append( enc ); + item.setEnclosures( encs ); + } +} + +static void readAuthor( KRss::RssItem& item, QXmlStreamReader& reader ) +{ + KRss::Person author; + int depth =3D 1; + while ( !reader.atEnd() && depth > 0 ) + { + reader.readNext(); + if ( reader.isEndElement() ) + --depth; + else if ( reader.isStartElement() ) + { + if ( Elements::instance.name.isNextIn( reader ) ) + author.setName( reader.readElementText() ); + else if ( Elements::instance.uri.isNextIn( reader ) ) + author.setUri( reader.readElementText() ); + else if ( Elements::instance.email.isNextIn( reader ) ) + author.setEmail( reader.readElementText() ); + } + + } + QList authors =3D item.authors(); + authors.append( author ); + item.setAuthors( authors ); +} + +static void readCategory( KRss::RssItem& item, QXmlStreamReader& reader ) +{ + const QXmlStreamAttributes attrs =3D reader.attributes(); + KRss::Category cat; + cat.setTerm( attrs.value( QString(), QLatin1String("term") ).toString(= ) ); + cat.setScheme( attrs.value( QString(), QLatin1String("scheme") ).toStr= ing() ); + cat.setLabel( attrs.value( QString(), QLatin1String("label") ).toStrin= g() ); + QList cats =3D item.categories(); + cats.append( cat ); + item.setCategories( cats ); +} + +static void readCustomProperty( KRss::RssItem& item, QXmlStreamReader& rea= der ) +{ + QString key; + QString value; + int depth =3D 1; + while ( !reader.atEnd() && depth > 0 ) + { + reader.readNext(); + if ( reader.isEndElement() ) + --depth; + else if ( reader.isStartElement() ) + { + if ( Elements::instance.key.isNextIn( reader ) ) + key =3D reader.readElementText(); + else if ( Elements::instance.value.isNextIn( reader ) ) + value =3D reader.readElementText(); + } + } + item.setCustomProperty( key, value ); +} + +} // namespace + +void KRss::RssItemSerializer::serialize( const KRss::RssItem& item, QByteA= rray& array, ItemPart part ) +{ + QXmlStreamWriter writer( &array ); + writer.writeStartDocument(); + ::writeItem( item, writer, part ); + writer.writeEndDocument(); +} + +bool KRss::RssItemSerializer::deserialize( KRss::RssItem& item, const QByt= eArray& array, ItemPart part ) +{ + QXmlStreamReader reader( array ); + reader.setNamespaceProcessing( true ); + + const bool readHeaders =3D ( part & Headers ) !=3D 0; + const bool readContent =3D ( part & Content ) !=3D 0; + + if ( readHeaders ) + item.setHeadersLoaded( true ); + + if ( readContent ) + item.setContentLoaded( true ); + + while ( !reader.atEnd() ) + { + reader.readNext(); + if ( reader.isStartElement() ) + { + if ( readContent ) { + if ( Elements::instance.summary.isNextIn( reader ) ) + item.setDescription( reader.readElementText() ); + else if ( Elements::instance.content.isNextIn( reader ) ) + item.setContent( reader.readElementText() ); + else if ( Elements::instance.language.isNextIn( reader ) ) + item.setLanguage( reader.readElementText() ); + else if ( Elements::instance.commentsLink.isNextIn( reader= ) ) + item.setCommentsLink( reader.readElementText() ); + else if ( Elements::instance.commentPostUri.isNextIn( read= er ) ) + item.setCommentPostUri( reader.readElementText() ); + else if ( Elements::instance.commentsCount.isNextIn( reade= r ) ) + item.setCommentsCount( reader.readElementText().toInt(= ) ); + else if ( Elements::instance.commentsFeed.isNextIn( reader= ) ) + item.setCommentsFeed( reader.readElementText() ); + else if ( Elements::instance.customProperty.isNextIn( read= er ) ) + ::readCustomProperty( item, reader ); + } + if ( readHeaders ) { + if ( Elements::instance.title.isNextIn( reader ) ) + item.setTitle( reader.readElementText() ); + else if ( Elements::instance.guid.isNextIn( reader ) ) + item.setGuid( reader.readElementText() ); + else if ( Elements::instance.hash.isNextIn( reader ) ) + item.setHash( reader.readElementText().toInt() ); + else if ( Elements::instance.guidIsHash.isNextIn( reader )= ) + item.setGuidIsHash( QVariant( reader.readElementText()= ).toBool() ); + else if ( Elements::instance.sourceFeedId.isNextIn( reader= ) ) + item.setSourceFeedId( reader.readElementText().toInt()= ); + else if ( Elements::instance.link.isNextIn( reader ) ) + ::readLink( item, reader ); + else if ( Elements::instance.author.isNextIn( reader ) ) + ::readAuthor( item, reader ); + else if ( Elements::instance.category.isNextIn( reader ) ) + ::readCategory( item, reader ); + else if ( Elements::instance.published.isNextIn( reader ) ) + item.setDatePublished( KDateTime::fromString( reader.r= eadElementText(), KDateTime::ISODate ) ); + else if ( Elements::instance.updated.isNextIn( reader ) ) + item.setDateUpdated( KDateTime::fromString( reader.rea= dElementText(), KDateTime::ISODate ) ); + } + } + } + return !reader.hasError(); +} diff --git a/plugins/tests/CMakeLists.txt b/plugins/tests/CMakeLists.txt new file mode 100644 index 0000000..bce1783 --- /dev/null +++ b/plugins/tests/CMakeLists.txt @@ -0,0 +1,52 @@ +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../krss +) + +macro(add_simple_test _testName) + set(_targetName ${_testName}) + set(_srcList ${ARGN}) + kde4_add_unit_test(${_targetName} ${_srcList}) + target_link_libraries(${_targetName} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIB= RARY} ${QT_QTTEST_LIBRARY} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_SYNDICAT= ION_LIBS} ${KDE4_KDECORE_LIBS} krss) +endmacro(add_simple_test) + +set(testxmlitemserializer_SRCS + testxmlitemserializer.cpp +) + +if(KRSS_ENABLE_PROTOBUF_SERIALIZER) + WRAP_PROTO(krss_LIB_PROTOBUF_SRCS krss.proto) + + set(testxmlitemserializer_SRCS + ${testxmlitemserializer_SRCS} + ${krss_LIB_PROTOBUF_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../rssitemserializer_protobuf.cpp + ) + set(KRSS_EXTRA_LIBS ${PROTOBUF_LIBRARY}) +else(KRSS_ENABLE_PROTOBUF_SERIALIZER) +if(KRSS_ENABLE_QDATASTREAM_SERIALIZER) + set(testxmlitemserializer_SRCS + ${testxmlitemserializer_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../rssitemserializer_qdatastream.cpp + ) + set(KRSS_EXTRA_LIBS ${PROTOBUF_LIBRARY}) +else(KRSS_ENABLE_QDATASTREAM_SERIALIZER) +if(KRSS_ENABLE_JSON_SERIALIZER) + set(testxmlitemserializer_SRCS + ${testxmlitemserializer_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../rssitemserializer_json.cpp + ) + set(KRSS_EXTRA_LIBS qjson) +else(KRSS_ENABLE_JSON_SERIALIZER) + set(testxmlitemserializer_SRCS + ${testxmlitemserializer_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../rssitemserializer_xml.cpp + ) +endif(KRSS_ENABLE_JSON_SERIALIZER) +endif(KRSS_ENABLE_QDATASTREAM_SERIALIZER) +endif(KRSS_ENABLE_PROTOBUF_SERIALIZER) + +add_simple_test(testxmlitemserializer ${testxmlitemserializer_SRCS}) diff --git a/plugins/tests/testxmlitemserializer.cpp b/plugins/tests/testxm= litemserializer.cpp new file mode 100644 index 0000000..f333015 --- /dev/null +++ b/plugins/tests/testxmlitemserializer.cpp @@ -0,0 +1,198 @@ +/* + * This file is part of the krss library + * + * Copyright (C) 2007 Frank Osterfeld + * + * 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 Licen= se + * 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 "testxmlitemserializer.h" + +#include +#include +#include +#include +#include +#include "rssitemserializer.h" + +#include + +#include + +#include +#include +#include + +using namespace KRss; + +namespace { + +void printItem( const RssItem& item ) +{ + QByteArray ba; + RssItemSerializer::serialize( item, ba ); + qDebug() << ba.size() << ba; +} + +void testItem( const RssItem& item ) +{ + const bool headersLoaded =3D item.headersLoaded(); + const bool contentLoaded =3D item.contentLoaded(); + QByteArray ba; + RssItemSerializer::serialize( item, ba ); + RssItem deserialized; + const bool success =3D RssItemSerializer::deserialize( deserialized, b= a ); + QVERIFY2( success, "Deserialization failed" ); + deserialized.setContentLoaded( contentLoaded ); + deserialized.setHeadersLoaded( headersLoaded ); + if ( item !=3D deserialized ) + { + printItem( item ); + printItem( deserialized ); + } + QCOMPARE( item, deserialized ); +} + +} + +void TestXmlItemSerializer::testEmptyItem() +{ + ::testItem( RssItem() ); +} + +void TestXmlItemSerializer::testDates() +{ + RssItem item; + const KDateTime updated =3D KDateTime::currentLocalDateTime(); + const KDateTime published =3D updated.addDays( -4 ); + item.setDatePublished( published ); + item.setDateUpdated( updated ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testSimpleItems() +{ + RssItem item; + item.setTitle( QLatin1String("Some title") ); + item.setDescription( QLatin1String("Some description") ); + item.setLink( QLatin1String("http://akregator.kde.org") ); + item.setContent( QLatin1String("Content makes the world go round") ); + item.setGuid( QLatin1String("http://uniqueid") ); + item.setGuidIsHash( true ); + item.setLanguage( QLatin1String("en") ); + item.setHash( 5 ); + ::testItem( item ); + item.setHash( 0 ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testStatus() +{ +#if 0 + RssItem item; + item.setStatus( Read ); + ::testItem( item ); + item.setStatus( New ); + ::testItem( item ); + item.setStatus( Important ); + ::testItem( item ); + item.setStatus( Read | Important ); + ::testItem( item ); +#endif +} + +void TestXmlItemSerializer::testCustomProperties() +{ + RssItem item; + item.setGuid( QLatin1String("http://uniqueid") ); + item.setTitle( QLatin1String("Some title") ); + item.setDescription( QLatin1String("Some description") ); + item.setLink( QLatin1String("http://akregator.kde.org") ); + item.setCustomProperty( QLatin1String("foo"), QLatin1String("bar") ); + item.setCustomProperty( QLatin1String("bar"), QLatin1String("foo") ); + item.setCustomProperty( QLatin1String("foobar"), QString() ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testEnclosures() +{ + RssItem item; + item.setLink( QLatin1String("http://akregator.kde.org") ); + Enclosure enc; + enc.setUrl( QLatin1String("http://akregator.kde.org/some.mp3") ); + enc.setType( QLatin1String("audio/mpeg") ); + enc.setTitle( QLatin1String("This is an enclosure!") ); + enc.setLength( 123456789 ); + Enclosure enc2 =3D enc; + enc.setDuration( 60 ); + QList encs; + encs.append( enc ); + encs.append( enc2 ); + item.setEnclosures( encs ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testCategories() +{ + Category cat; + cat.setTerm( QLatin1String("term1") ); + cat.setScheme( QLatin1String("http://Blabla#") ); + cat.setLabel( QLatin1String("Term 1") ); + Category cat2; + cat2.setTerm( QLatin1String("Term2") ); + cat2.setLabel( QLatin1String("Tada") ); + QList cats; + cats.append( cat ); + cats.append( cat2 ); + cats.append( Category() ); + RssItem item; + item.setCategories( cats ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testAuthors() +{ + Person a1; + a1.setName( QLatin1String("John Doe") ); + Person a2; + a2.setName( QLatin1String("John Doe") ); + a2.setUri( QLatin1String("http://doeweb.net/John") ); + a2.setEmail( QLatin1String("joe@doeweb.net") ); + Person a3; + QList authors; + authors.append( a1 ); + authors.append( a2 ); + authors.append( a3 ); + RssItem item; + item.setAuthors( authors ); + ::testItem( item ); +} + +void TestXmlItemSerializer::testComments() +{ + RssItem item; + item.setCommentsCount( 10 ); + item.setCommentsLink( QLatin1String("http://heyho#comment") ); + item.setCommentsFeed( QLatin1String("http://heyho/comments.rss") ); + item.setCommentPostUri( QLatin1String("http://whatever") ); + ::testItem( item ); +} + + +QTEST_KDEMAIN( TestXmlItemSerializer, NoGUI ) + +#include "testxmlitemserializer.moc" diff --git a/plugins/tests/testxmlitemserializer.h b/plugins/tests/testxmli= temserializer.h new file mode 100644 index 0000000..427161c --- /dev/null +++ b/plugins/tests/testxmlitemserializer.h @@ -0,0 +1,44 @@ +/* + * This file is part of the kfeed library + * + * Copyright (C) 2007 Frank Osterfeld + * + * 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 Licen= se + * 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. + * + */ + +#ifndef TESTXMLITEMSERIALIZER_H +#define TESTXMLITEMSERIALIZER_H + +#include + +class TestXmlItemSerializer : public QObject { + Q_OBJECT +private: + +private Q_SLOTS: + void testEmptyItem(); + void testSimpleItems(); + void testEnclosures(); + void testCategories(); + void testAuthors(); + void testComments(); + void testDates(); + void testStatus(); + void testCustomProperties(); +}; + +#endif // TESTXMLITEMSERIALIZER_H