00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "parser.h"
00024 #include "document.h"
00025 #include "model.h"
00026 #include "modelmaker.h"
00027 #include "property.h"
00028 #include "rdfvocab.h"
00029 #include "resource.h"
00030 #include "rssvocab.h"
00031 #include "statement.h"
00032
00033 #include <documentsource.h>
00034
00035 #include <QtXml/QDomDocument>
00036 #include <QtXml/QDomNodeList>
00037 #include <QtCore/QHash>
00038 #include <QtCore/QList>
00039 #include <QtCore/QMap>
00040 #include <QtCore/QString>
00041 #include <QtCore/QStringList>
00042
00043 namespace Syndication {
00044 namespace RDF {
00045
00046 class Parser::ParserPrivate
00047 {
00048 public:
00049 QDomDocument addEnumeration(const QDomDocument& doc);
00050 void map09to10(Model model);
00051 void addSequenceFor09(Model model);
00052
00053 QString strInternalNs;
00054 QString strItemIndex;
00055 };
00056
00057 bool Parser::accept(const DocumentSource& source) const
00058 {
00059 QDomDocument doc = source.asDomDocument();
00060
00061 if (doc.isNull())
00062 return false;
00063 QDomElement root = doc.documentElement();
00064
00065 if (!root.isElement())
00066 return false;
00067
00068 return root.namespaceURI() == RDFVocab::self()->namespaceURI();
00069 }
00070
00071 SpecificDocumentPtr Parser::parse(const DocumentSource& source) const
00072 {
00073 QDomDocument doc = source.asDomDocument();
00074
00075 if (doc.isNull())
00076 return Syndication::SpecificDocumentPtr(new Document());
00077
00078 doc = d->addEnumeration(doc);
00079
00080 ModelMaker maker;
00081 Model model = maker.createFromXML(doc);
00082
00083 bool is09 = !model.resourcesWithType(RSS09Vocab::self()->channel()).isEmpty();
00084
00085 if (is09)
00086 {
00087 d->map09to10(model);
00088 d->addSequenceFor09(model);
00089 }
00090
00091 QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel());
00092
00093 if (channels.isEmpty())
00094 return Syndication::SpecificDocumentPtr(new Document());
00095
00096 return DocumentPtr(new Document(*(channels.begin())));
00097 }
00098
00099 QDomDocument Parser::ParserPrivate::addEnumeration(const QDomDocument& docp)
00100 {
00101 QDomDocument doc(docp);
00102
00103 QDomNodeList list = doc.elementsByTagNameNS(RSS09Vocab::self()->namespaceURI(),
00104 QString::fromUtf8("item"));
00105
00106 for (int i = 0; i < list.size(); ++i)
00107 {
00108 QDomElement item = list.item(i).toElement();
00109 if (!item.isNull())
00110 {
00111 QDomElement ie = doc.createElementNS(strInternalNs, strItemIndex);
00112 item.appendChild(ie);
00113 ie.appendChild(doc.createTextNode(QString::number(i)));
00114
00115 }
00116 }
00117
00118 return doc;
00119 }
00120
00121 void Parser::ParserPrivate::map09to10(Model model)
00122 {
00123 QHash<QString, PropertyPtr> hash;
00124
00125 hash.insert(RSS09Vocab::self()->title()->uri(), RSSVocab::self()->title());
00126 hash.insert(RSS09Vocab::self()->description()->uri(), RSSVocab::self()->description());
00127 hash.insert(RSS09Vocab::self()->link()->uri(), RSSVocab::self()->link());
00128 hash.insert(RSS09Vocab::self()->name()->uri(), RSSVocab::self()->name());
00129 hash.insert(RSS09Vocab::self()->url()->uri(), RSSVocab::self()->url());
00130 hash.insert(RSS09Vocab::self()->image()->uri(), RSSVocab::self()->image());
00131 hash.insert(RSS09Vocab::self()->textinput()->uri(), RSSVocab::self()->textinput());
00132
00133 QStringList uris09 = RSS09Vocab::self()->properties();
00134
00135
00136
00137 QList<StatementPtr> statements = model.statements();
00138 QList<StatementPtr>::ConstIterator it = statements.constBegin();
00139 QList<StatementPtr>::ConstIterator end = statements.constEnd();
00140
00141 for ( ; it != end; ++it)
00142 {
00143 StatementPtr stmt = *it;
00144
00145 QString predUri = stmt->predicate()->uri();
00146 if (uris09.contains(predUri))
00147 {
00148 model.addStatement(stmt->subject(), hash[predUri], stmt->object());
00149 }
00150 }
00151
00152 QList<ResourcePtr> channels = model.resourcesWithType(RSS09Vocab::self()->channel());
00153
00154 ResourcePtr channel;
00155
00156 if (!channels.isEmpty())
00157 {
00158 channel = *(channels.begin());
00159
00160 model.removeStatement(channel, RDFVocab::self()->type(), RSS09Vocab::self()->channel());
00161 model.addStatement(channel, RDFVocab::self()->type(), RSSVocab::self()->channel());
00162 }
00163 }
00164
00165 void Parser::ParserPrivate::addSequenceFor09(Model model)
00166 {
00167 const QList<ResourcePtr> items = model.resourcesWithType(RSS09Vocab::self()->item());
00168
00169 if (items.isEmpty())
00170 return;
00171
00172 const QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel());
00173
00174 if (channels.isEmpty())
00175 return;
00176
00177 PropertyPtr itemIndex = model.createProperty(strInternalNs + strItemIndex);
00178
00179
00180 QMap<uint, ResourcePtr> sorted;
00181
00182 foreach (const ResourcePtr &i, items)
00183 {
00184 QString numstr = i->property(itemIndex)->asString();
00185 bool ok = false;
00186 uint num = numstr.toUInt(&ok);
00187 if (ok)
00188 {
00189 sorted[num] = i;
00190 }
00191 }
00192
00193 SequencePtr seq = model.createSequence();
00194 model.addStatement(channels.first(), RSSVocab::self()->items(), seq);
00195
00196 foreach (const ResourcePtr &i, sorted)
00197 {
00198 seq->append(i);
00199 model.addStatement(seq, RDFVocab::self()->li(), i);
00200 }
00201 }
00202
00203 Parser::Parser() : d(new ParserPrivate)
00204 {
00205 d->strInternalNs = QString::fromUtf8("http://akregator.sf.net/libsyndication/internal#");
00206 d->strItemIndex = QString::fromUtf8("itemIndex");
00207 }
00208
00209 Parser::~Parser()
00210 {
00211 delete d;
00212 }
00213
00214 Parser::Parser(const Parser& other) : AbstractParser(other), d(0) {}
00215 Parser& Parser::operator=(const Parser& ) { return *this; }
00216
00217 QString Parser::format() const
00218 {
00219 return QString::fromUtf8("rdf");
00220 }
00221
00222
00223 }
00224 }