mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
230 lines
6.6 KiB
C++
230 lines
6.6 KiB
C++
/*
|
|
* This file is part of the syndication library
|
|
*
|
|
* Copyright (C) 2006 Frank Osterfeld <osterfeld@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.
|
|
*
|
|
*/
|
|
|
|
#include "parser.h"
|
|
#include "document.h"
|
|
#include "model.h"
|
|
#include "modelmaker.h"
|
|
#include "property.h"
|
|
#include "rdfvocab.h"
|
|
#include "resource.h"
|
|
#include "rssvocab.h"
|
|
#include "statement.h"
|
|
|
|
#include <documentsource.h>
|
|
|
|
#include <QtXml/QDomDocument>
|
|
#include <QtXml/QDomNodeList>
|
|
#include <QtCore/QHash>
|
|
#include <QtCore/QList>
|
|
#include <QtCore/QMap>
|
|
#include <QtCore/QString>
|
|
#include <QtCore/QStringList>
|
|
|
|
namespace Syndication {
|
|
namespace RDF {
|
|
|
|
class Parser::ParserPrivate
|
|
{
|
|
public:
|
|
QDomDocument addEnumeration(const QDomDocument& doc);
|
|
void map09to10(Model model);
|
|
void addSequenceFor09(Model model);
|
|
|
|
QString strInternalNs;
|
|
QString strItemIndex;
|
|
};
|
|
|
|
bool Parser::accept(const DocumentSource& source) const
|
|
{
|
|
QDomDocument doc = source.asDomDocument();
|
|
|
|
if (doc.isNull())
|
|
return false;
|
|
QDomElement root = doc.documentElement();
|
|
|
|
if (!root.isElement())
|
|
return false;
|
|
|
|
return root.namespaceURI() == RDFVocab::self()->namespaceURI();
|
|
}
|
|
|
|
SpecificDocumentPtr Parser::parse(const DocumentSource& source) const
|
|
{
|
|
QDomDocument doc = source.asDomDocument();
|
|
|
|
if (doc.isNull())
|
|
return Syndication::SpecificDocumentPtr(new Document());
|
|
|
|
doc = d->addEnumeration(doc);
|
|
|
|
ModelMaker maker;
|
|
Model model = maker.createFromXML(doc);
|
|
|
|
bool is09 = !model.resourcesWithType(RSS09Vocab::self()->channel()).isEmpty();
|
|
|
|
if (is09)
|
|
{
|
|
d->map09to10(model);
|
|
d->addSequenceFor09(model);
|
|
}
|
|
|
|
QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel());
|
|
|
|
if (channels.isEmpty())
|
|
return Syndication::SpecificDocumentPtr(new Document());
|
|
|
|
return DocumentPtr(new Document(*(channels.begin())));
|
|
}
|
|
|
|
QDomDocument Parser::ParserPrivate::addEnumeration(const QDomDocument& docp)
|
|
{
|
|
QDomDocument doc(docp);
|
|
|
|
QDomNodeList list = doc.elementsByTagNameNS(RSS09Vocab::self()->namespaceURI(),
|
|
QLatin1String("item"));
|
|
|
|
for (int i = 0; i < list.size(); ++i)
|
|
{
|
|
QDomElement item = list.item(i).toElement();
|
|
if (!item.isNull())
|
|
{
|
|
QDomElement ie = doc.createElementNS(strInternalNs, strItemIndex);
|
|
item.appendChild(ie);
|
|
ie.appendChild(doc.createTextNode(QString::number(i)));
|
|
|
|
}
|
|
}
|
|
|
|
return doc;
|
|
}
|
|
|
|
void Parser::ParserPrivate::map09to10(Model model)
|
|
{
|
|
QHash<QString, PropertyPtr> hash;
|
|
|
|
hash.insert(RSS09Vocab::self()->title()->uri(), RSSVocab::self()->title());
|
|
hash.insert(RSS09Vocab::self()->description()->uri(), RSSVocab::self()->description());
|
|
hash.insert(RSS09Vocab::self()->link()->uri(), RSSVocab::self()->link());
|
|
hash.insert(RSS09Vocab::self()->name()->uri(), RSSVocab::self()->name());
|
|
hash.insert(RSS09Vocab::self()->url()->uri(), RSSVocab::self()->url());
|
|
hash.insert(RSS09Vocab::self()->image()->uri(), RSSVocab::self()->image());
|
|
hash.insert(RSS09Vocab::self()->textinput()->uri(), RSSVocab::self()->textinput());
|
|
|
|
QStringList uris09 = RSS09Vocab::self()->properties();
|
|
|
|
// map statement predicates to RSS 1.0
|
|
|
|
QList<StatementPtr> statements = model.statements();
|
|
QList<StatementPtr>::ConstIterator it = statements.constBegin();
|
|
QList<StatementPtr>::ConstIterator end = statements.constEnd();
|
|
|
|
for ( ; it != end; ++it)
|
|
{
|
|
StatementPtr stmt = *it;
|
|
|
|
QString predUri = stmt->predicate()->uri();
|
|
if (uris09.contains(predUri))
|
|
{
|
|
model.addStatement(stmt->subject(), hash[predUri], stmt->object());
|
|
}
|
|
}
|
|
// map channel type
|
|
QList<ResourcePtr> channels = model.resourcesWithType(RSS09Vocab::self()->channel());
|
|
|
|
ResourcePtr channel;
|
|
|
|
if (!channels.isEmpty())
|
|
{
|
|
channel = *(channels.begin());
|
|
|
|
model.removeStatement(channel, RDFVocab::self()->type(), RSS09Vocab::self()->channel());
|
|
model.addStatement(channel, RDFVocab::self()->type(), RSSVocab::self()->channel());
|
|
}
|
|
}
|
|
|
|
void Parser::ParserPrivate::addSequenceFor09(Model model)
|
|
{
|
|
//RDF 0.9 doesn't contain an item sequence, and the items don't have rdf:about, so add both
|
|
|
|
const QList<ResourcePtr> items = model.resourcesWithType(RSS09Vocab::self()->item());
|
|
|
|
if (items.isEmpty())
|
|
return;
|
|
|
|
const QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel());
|
|
|
|
if (channels.isEmpty())
|
|
return;
|
|
|
|
PropertyPtr itemIndex = model.createProperty(strInternalNs + strItemIndex);
|
|
|
|
// use QMap here, not QHash. as we need the sorting functionality
|
|
QMap<uint, ResourcePtr> sorted;
|
|
|
|
foreach (const ResourcePtr &i, items)
|
|
{
|
|
QString numstr = i->property(itemIndex)->asString();
|
|
bool ok = false;
|
|
uint num = numstr.toUInt(&ok);
|
|
if (ok)
|
|
{
|
|
sorted[num] = i;
|
|
}
|
|
}
|
|
|
|
SequencePtr seq = model.createSequence();
|
|
model.addStatement(channels.first(), RSSVocab::self()->items(), seq);
|
|
|
|
foreach (const ResourcePtr &i, sorted)
|
|
{
|
|
seq->append(i);
|
|
// add rdf:about (type)
|
|
model.addStatement(i, RDFVocab::self()->type(), RSSVocab::self()->item());
|
|
|
|
//add to items sequence
|
|
model.addStatement(seq, RDFVocab::self()->li(), i);
|
|
}
|
|
}
|
|
|
|
Parser::Parser() : d(new ParserPrivate)
|
|
{
|
|
d->strInternalNs = QLatin1String("http://akregator.sf.net/libsyndication/internal#");
|
|
d->strItemIndex = QLatin1String("itemIndex");
|
|
}
|
|
|
|
Parser::~Parser()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
Parser::Parser(const Parser& other) : AbstractParser(other), d(0) {}
|
|
Parser& Parser::operator=(const Parser& /*other*/) { return *this; }
|
|
|
|
QString Parser::format() const
|
|
{
|
|
return QLatin1String("rdf");
|
|
}
|
|
|
|
|
|
} // namespace RDF
|
|
} // namespace Syndication
|