Warning, file /office/calligra/libs/text/KoTextRdfCore.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2010 KO GmbH <ben.martin@kogmbh.com>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "KoTextRdfCore.h"
0021 
0022 #include "TextDebug.h"
0023 #include <KoStoreDevice.h>
0024 #include <KoXmlWriter.h>
0025 #include <QFile>
0026 
0027 using namespace Soprano;
0028 
0029 bool KoTextRdfCore::saveRdf( QSharedPointer<Soprano::Model> model, Soprano::StatementIterator triples, KoStore *store, KoXmlWriter *manifestWriter, const QString &fileName)
0030 {
0031     bool ok = false;
0032 
0033     if (! store->open(fileName)) {
0034         return false;
0035     }
0036 
0037     KoStoreDevice dev(store);
0038     QTextStream oss(&dev);
0039 
0040     QString serialization = "application/rdf+xml";
0041     const Soprano::Serializer* serializer
0042             = Soprano::PluginManager::instance()->discoverSerializerForSerialization(
0043                     Soprano::SerializationRdfXml);
0044 
0045     if (serializer) {
0046         QString data;
0047         QTextStream tss(&data);
0048         if (serializer->serialize(triples, tss, Soprano::SerializationRdfXml)) {
0049             tss.flush();
0050             oss << data;
0051             debugText << "fileName:" << fileName << " data.sz:" << data.size();
0052             debugText << "model.sz:" << model->statementCount();
0053             ok = true;
0054         } else {
0055             debugText << "serialization of Rdf failed!";
0056         }
0057     }
0058     oss.flush();
0059     store->close();
0060     manifestWriter->addManifestEntry(fileName, "application/rdf+xml");
0061     return ok;
0062 }
0063 
0064 bool KoTextRdfCore::createAndSaveManifest(QSharedPointer<Soprano::Model> docmodel, const QMap<QString, QString> &idmap, KoStore *store, KoXmlWriter *manifestWriter)
0065 {
0066     QSharedPointer<Soprano::Model> tmpmodel(Soprano::createModel());
0067     QMap<QString, QString>::const_iterator iditer = idmap.constBegin();
0068     QMap<QString, QString>::const_iterator idend = idmap.constEnd();
0069     for (; iditer != idend; ++iditer) {
0070         QString oldID = iditer.key();
0071         QString newID = iditer.value();
0072         debugText << "oldID:" << oldID << " newID:" << newID;
0073         QString sparqlQuery;
0074         QTextStream queryss(&sparqlQuery);
0075         queryss << ""
0076             << "prefix pkg:  <http://docs.oasis-open.org/ns/office/1.2/meta/pkg#> \n"
0077             << ""
0078             << "select ?s ?p ?o \n"
0079             << "where { \n"
0080             << " ?s pkg:idref ?xmlid . \n"
0081             << " ?s ?p ?o . \n"
0082             << " filter( str(?xmlid) = \"" << oldID << "\" ) \n"
0083             << "}\n";
0084 
0085         Soprano::QueryResultIterator it =
0086             docmodel->executeQuery(sparqlQuery,
0087                                    Soprano::Query::QueryLanguageSparql);
0088         while (it.next()) {
0089             Soprano::Node pred = it.binding("p");
0090             Soprano::Node obj  = it.binding("o");
0091             if (pred.toString() == "http://docs.oasis-open.org/ns/office/1.2/meta/pkg#idref") {
0092                 debugText << "changing idref, oldID:" << oldID << " newID:" << newID;
0093                 obj = Node::createLiteralNode(newID);
0094             }
0095             Statement s(it.binding("s"), pred, obj);
0096             tmpmodel->addStatement(s);
0097         }
0098     }
0099     debugText << "exporting triples model.sz:" << tmpmodel->statementCount();
0100     // save tmpmodel as manifest.rdf in C+P ODF file.
0101     Soprano::StatementIterator triples = tmpmodel->listStatements();
0102     bool ret = saveRdf(tmpmodel, triples, store, manifestWriter, "manifest.rdf");
0103     return ret;
0104 }
0105 
0106 bool KoTextRdfCore::loadManifest(KoStore *store, QSharedPointer<Soprano::Model> model)
0107 {
0108     bool ok = true;
0109     QString fileName = "manifest.rdf";
0110     if (!store->open(fileName)) {
0111         debugText << "Entry " << fileName << " not found!";
0112         return false;
0113     }
0114     Soprano::Node context(QUrl("http://www.calligra.org/Rdf/path/" + fileName));
0115     QUrl BaseURI = QUrl("");
0116     debugText << "Loading external Rdf/XML from:" << fileName;
0117 
0118     QString rdfxmlData(store->device()->readAll());
0119     const Soprano::Parser *parser =
0120         Soprano::PluginManager::instance()->discoverParserForSerialization(
0121             Soprano::SerializationRdfXml);
0122     Soprano::StatementIterator it = parser->parseString(rdfxmlData,
0123                                     BaseURI,
0124                                     Soprano::SerializationRdfXml);
0125     QList<Statement> allStatements = it.allElements();
0126     debugText << "Found " << allStatements.size() << " triples...";
0127     foreach (const Soprano::Statement &s, allStatements) {
0128         Error::ErrorCode err = model->addStatement(s.subject(), s.predicate(),
0129                 s.object(), context);
0130         if (err != Error::ErrorNone) {
0131             debugText << "Error adding triple! s:" << s.subject()
0132                 << " p:" << s.predicate()
0133                 << " o:" << s.object();
0134             ok = false;
0135             break;
0136         }
0137     }
0138     store->close();
0139     return ok;
0140 }
0141 
0142 void KoTextRdfCore::dumpModel(const QString &msg, QSharedPointer<Soprano::Model> m)
0143 {
0144 #ifndef NDEBUG
0145     QList<Soprano::Statement> allStatements = m->listStatements().allElements();
0146     debugText << "----- " << msg << " ----- model size:" << allStatements.size() << endl;
0147     foreach (const Soprano::Statement &s, allStatements) {
0148         debugText << s;
0149     }
0150 #else
0151     Q_UNUSED(msg);
0152     Q_UNUSED(m);
0153 #endif
0154 }
0155 
0156 QList<Soprano::Statement> KoTextRdfCore::loadList(QSharedPointer<Soprano::Model> model, Soprano::Node ListHeadSubject)
0157 {
0158     Node rdfNil = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
0159     Node rdfFirst = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"));
0160     Node rdfRest = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"));
0161 
0162     Soprano::Node listBNode = ListHeadSubject;
0163     QList<Statement> ret;
0164     debugText << "finding all nodes in the list...";
0165     while (true) {
0166         ret << model->listStatements(listBNode, rdfFirst, Node()).allElements();
0167         Soprano::Node obj = KoTextRdfCore::getObject(model, listBNode, rdfRest);
0168         debugText << "ret:" << ret;
0169         debugText << "rest:" << obj;
0170         if (!obj.isValid()) {
0171             break;
0172         }
0173         if (obj.toString() == rdfNil.toString()) {
0174             break;
0175         }
0176         listBNode = obj;
0177     }
0178     return ret;
0179 }
0180 
0181 static void removeList(QSharedPointer<Soprano::Model> model, Soprano::Node ListHeadSubject)
0182 {
0183     Node rdfNil = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
0184     Node rdfFirst = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"));
0185     Node rdfRest = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"));
0186     //
0187     // Chain down the list recursively so we delete from
0188     // the list tail back to the head.
0189     //
0190     Soprano::Node obj = KoTextRdfCore::getObject(model, ListHeadSubject, rdfRest);
0191     if (obj.isValid()) {
0192         if (obj.toString() != rdfNil.toString()) {
0193             removeList(model, obj);
0194         }
0195     }
0196     model->removeAllStatements(ListHeadSubject, rdfFirst, Node());
0197     model->removeAllStatements(ListHeadSubject, rdfRest, Node());
0198 }
0199 
0200 void KoTextRdfCore::saveList(QSharedPointer<Soprano::Model> model, Soprano::Node ListHeadSubject, QList<Soprano::Node> &dataBNodeList, Soprano::Node context)
0201 {
0202     Node rdfNil = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
0203     Node rdfFirst = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"));
0204     Node rdfRest = Node::createResourceNode(QUrl("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"));
0205 
0206     debugText << "header:" << ListHeadSubject.toString();
0207     debugText << "list.sz:" << dataBNodeList.size();
0208     debugText << "context:" << context.toString();
0209 
0210     removeList(model, ListHeadSubject);
0211 
0212     Soprano::Node listBNode = ListHeadSubject;
0213     Soprano::Node prevListBNode;
0214 
0215     foreach (const Soprano::Node &dataBNode, dataBNodeList) {
0216         // Link the list in Rdf
0217         model->addStatement(listBNode, rdfFirst, dataBNode, context);
0218         if (prevListBNode.isValid()) {
0219             debugText << "prev:" << prevListBNode << " current:" << listBNode;
0220             model->addStatement(prevListBNode, rdfRest, listBNode, context);
0221         }
0222         prevListBNode = listBNode;
0223         listBNode = model->createBlankNode();
0224     }
0225 
0226     debugText << "at end, prev.isValid:" << prevListBNode.isValid();
0227     if (prevListBNode.isValid()) {
0228         model->addStatement(prevListBNode, rdfRest, listBNode, context);
0229     }
0230     model->addStatement(listBNode, rdfRest, rdfNil, context);
0231 }
0232 
0233 void KoTextRdfCore::removeStatementsIfTheyExist( QSharedPointer<Soprano::Model> m, const QList<Soprano::Statement> &removeList)
0234 {
0235     foreach (const Soprano::Statement &s, removeList) {
0236         StatementIterator it = m->listStatements(s.subject(), s.predicate(), s.object(), s.context());
0237         QList<Statement> allStatements = it.allElements();
0238         foreach(const Soprano::Statement &z, allStatements) {
0239             debugText << "found:" << z;
0240             m->removeStatement(z);
0241         }
0242     }
0243 }
0244 
0245 Soprano::Node KoTextRdfCore::getObject(QSharedPointer<Soprano::Model> model, Soprano::Node s, Soprano::Node p)
0246 {
0247     QList<Statement> all;
0248     all = model->listStatements(s, p, Node()).allElements();
0249     if (all.isEmpty()) {
0250         return Soprano::Node();
0251     }
0252     return all.first().object();
0253 }
0254 
0255 QByteArray KoTextRdfCore::fileToByteArray(const QString &fileName)
0256 {
0257     QFile t(fileName);
0258     t.open(QIODevice::ReadOnly);
0259     return t.readAll();
0260 }
0261 
0262 QString KoTextRdfCore::getProperty(QSharedPointer<Soprano::Model> m, Soprano::Node subj, Soprano::Node pred, const QString &defval)
0263 {
0264     StatementIterator it = m->listStatements(subj, pred, Node());
0265     QList<Statement> allStatements = it.allElements();
0266     foreach (const Soprano::Statement &s, allStatements) {
0267         return s.object().toString();
0268     }
0269     return defval;
0270 }
0271 
0272 QString KoTextRdfCore::optionalBindingAsString(Soprano::QueryResultIterator &it, const QString &bindingName, const QString &def)
0273 {
0274     if (it.binding(bindingName).isValid()) {
0275         return it.binding(bindingName).toString();
0276     }
0277     return def;
0278 }