Warning, file /office/calligra/libs/rdf/KoDocumentRdf.h 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 #ifndef KO_DOCUMENT_Rdf_H
0021 #define KO_DOCUMENT_Rdf_H
0022 
0023 #include "kordf_export.h"
0024 #include "RdfForward.h"
0025 #include "KoSemanticStylesheet.h"
0026 #include "KoRdfSemanticItem.h"
0027 #include "KoRdfSemanticItemViewSite.h"
0028 #include "RdfSemanticTreeWidgetAction.h"
0029 #include "KoRdfSemanticTree.h"
0030 // Calligra
0031 #include <KoDocumentRdfBase.h>
0032 #include <KoXmlReaderForward.h>
0033 #include <KoDataCenterBase.h>
0034 // Soprano
0035 #include <Soprano/Soprano>
0036 // Qt
0037 #include <QObject>
0038 #include <QMap>
0039 #include <QString>
0040 #include <QStringList>
0041 #include <QTextBlockUserData>
0042 #include <QTreeWidgetItem>
0043 
0044 class QDomDocument;
0045 
0046 class KoStore;
0047 class KoXmlWriter;
0048 class KoDocument;
0049 class KoCanvasBase;
0050 class KoTextEditor;
0051 
0052 class KoDocumentRdfPrivate;
0053 
0054 class QAction;
0055 
0056 /**
0057  * @short The central access point for the Rdf metadata of an ODF document.
0058  *
0059  * @author Ben Martin <ben.martin@kogmbh.com>
0060  * @see KoDocument
0061  * @see KoDocumentInfo
0062  *
0063  * The KoDocumentRdf object is possibly associated with a KoDocument.
0064  * There does not need to be a KoDocumentRdf for each KoDocument, but
0065  * if one exists it is a one-to-one relationship. The KoDocumentRdf
0066  * is also associated with the KoDocumentResourceManager of a canvas.
0067  *
0068  * Once again, the canvas to KoDocumentRdf is either a 1-1 or 1 to
0069  * zero relationship.
0070  *
0071  * ACCESS TO Rdf:
0072  *
0073  * You can get at the Rdf information in two main ways: either using
0074  * Soprano/SPARQL or through KoRdfSemanticItem objects.
0075  *
0076  * Subclasses of KoRdfSemanticItem exist for locations (foaf,vcard),
0077  * events (ical), and locations (two Rdf geolocation formats). To get
0078  * a list of these objects use the foaf(), calendarEvents(), and
0079  * locations() methods of this class. Each of these methods optionally
0080  * takes a Soprano::Model and returns a list of SemanticItems of a
0081  * particular subclass. If you do not pass an Soprano::Model to the
0082  * methods the default model() of the KoDocumentRdf is used. By
0083  * allowing you to pass a model explicitly, you can find contacts that
0084  * exist in a subset of the full Rdf graph for a document. This is
0085  * useful if you want to find the contacts in the users current
0086  * "selection" in the document.
0087  *
0088  * For example, to find the foaf entries related to the current KoTextEditor
0089  *
0090  * Soprano::Model* model = rdf->findStatements( editor );
0091  * QList<hKoRdfSemanticItem> foaflist = rdf->semanticItems( "Contact", model );
0092  *
0093  * Using the Soprano::Model directly is covered in a latter section of
0094  * this comment.
0095  *
0096  * STORAGE OF Rdf:
0097  *
0098  * Broadly there are two ways Rdf metadata is stored in an ODF
0099  * document.
0100  *
0101  * 1) inline in the content.xml file in an Rdfa style, though not
0102  *    using the full Rdfa spec
0103  *
0104  * 2) externally in manifest.rdf or other Rdf/XML files linked to by
0105  * manifest.rdf
0106  *
0107  * The Rdf that is stored using these methods is collected and made
0108  * available by the KoDocumentRdf class. The inline Rdf using option
0109  * (1) is stored along with the Calligra C++ objects that are created
0110  * during document loading. This class also knows how to find the
0111  * scattered Rdf that option (1) loads. Leaving the Rdf from option
0112  * (1) scattered in the document allows it to be preserved in the
0113  * normal course of document editing such as copy and paste, undo and
0114  * redo operations.
0115  *
0116  * The scattered Rdf from option (1) is stored using the
0117  * KoTextInlineRdf class. You can convert a KoTextInlineRdf to
0118  * a Soprano::Statement with the toStatement() method of this class.
0119  *
0120  * LOW LEVEL Rdf ACCESS:
0121  *
0122  * The model() method will give you a Soprano::model with all the Rdf
0123  * for the document, be them from option (1) or (2) above.
0124  *
0125  * The findStatements() methods will give you a Soprano::model
0126  * containing the statements relevant to a cursor or xml:id in the
0127  * document. The xml:id is the same identifier that is used in the
0128  * content.xml file that was loaded.
0129  *
0130  * Note that the findStatements() returns a submodel containing only
0131  * the statements relevant to the xml:id or cursor position you
0132  * selected. This will be a subset of all the Rdf for the document.
0133  * The various expand() methods can be used to add more Rdf statements
0134  * from the document to the submodel returned by findStatements(). For
0135  * example, the expandStatementsReferencingSubject() method will
0136  * expand the soprano::model to add Rdf statements which refer to any
0137  * subject in the Rdf submodel you pass in.
0138  */
0139 class KORDF_EXPORT KoDocumentRdf : public KoDocumentRdfBase
0140 {
0141     Q_OBJECT
0142 public:
0143     /**
0144      * For Rdf stored in manifest.rdf or another rdf file referenced
0145      * by the manifest, this prefix is used as the start of the graph
0146      * context. The filename.rdf is appended so that the Rdf can be
0147      * put back into the right file again during save.
0148      */
0149     const static QString RDF_PATH_CONTEXT_PREFIX;
0150 
0151     /**
0152      * The constructor
0153      * @param parent a pointer to the parent object
0154      */
0155     explicit KoDocumentRdf(QObject *parent = 0);
0156 
0157     /** The destructor */
0158     ~KoDocumentRdf();
0159 
0160     /**
0161      * Load from an OASIS document
0162      * @param store the store with the metaInformation
0163      * @return true if success
0164      */
0165     bool loadOasis(KoStore *store);
0166 
0167     /**
0168      * Save to an OASIS document
0169      * @param store a pointer to a KoStore to save in
0170      * @param manifestWriter the document writer
0171      * @return true if success
0172      */
0173     bool saveOasis(KoStore *store, KoXmlWriter *manifestWriter);
0174 
0175     /**
0176      * Used by KoRdfSemanticItem when creating new semantic items so that the
0177      * KoDocumentRdf class can find them.
0178      */
0179     void rememberNewInlineRdfObject(KoTextInlineRdf *inlineRdf);
0180 
0181     /**
0182      * Find all the KoTextInlineRdf objects that exist in the
0183      * document and update the statements in the Soprano::(model) to
0184      * reflect the current state of the inline Rdf.
0185      */
0186     void updateInlineRdfStatements(const QTextDocument *qdoc);
0187 
0188     /**
0189      * During a save(), various Rdf objects in the document will
0190      * create new xmlid values which are used in the saved document.
0191      * As part of the save state a QMap from the old xmlid to the new
0192      * xmlid is built up. This method is then used to update the Rdf
0193      * triples to use the new xmlid values before that Rdf itself is
0194      * saved. This way the Rdf -> xmlid references will remain valid
0195      * in the saved ODF file.
0196      *
0197      * Since the Rdf is updated to use the new xmlid values, this method
0198      * also updates the C++ objects to use the new xmlid values so that
0199      * the instance of the document in memory is correctly linked.
0200      *
0201      * This way, Calligra is free to change the xml:id during save() and
0202      * the Rdf is still linked correctly.
0203      */
0204     void updateXmlIdReferences(const QMap<QString, QString> &m);
0205 
0206     /**
0207      * Get the namespace to URI prefix mapping object.
0208      */
0209     KoRdfPrefixMapping* prefixMapping() const;
0210 
0211     /**
0212      * Get the Soprano::Model that contains all the Rdf
0213      * You do not own the model, do not delete it.
0214      */
0215     virtual QSharedPointer<Soprano::Model> model() const;
0216 
0217     /**
0218      * Convert an inlineRdf object into a Soprano::Statement
0219      */
0220     Soprano::Statement toStatement(KoTextInlineRdf *inlineRdf) const;
0221 
0222     /**
0223      * Look for the semitem with the given xmlid and return the
0224      * start and end position for that semitem. If there is no semitem
0225      * with the \p xmlId then 0,0 is returned.
0226      */
0227     QPair<int, int> findExtent(const QString &xmlId) const;
0228 
0229     /**
0230      * Look for the semitem that is at or surrounding the cursor given. Note that if there
0231      * are nested semitems, the extend for the most nested semitem is returned.
0232      * for example, in the below scenario the return value will be QPair< start-b, end-b >.
0233      *
0234      * <start-a> ... <start-b> ... cursor ... <end-b> ... <end-a>
0235      */
0236     QPair<int, int> findExtent(KoTextEditor *handler) const;
0237 
0238     /**
0239      * find the xmlid of the semitem that is at or surrounding the cursor given. As with
0240      * findExtent() this will be only the most nested semitem.
0241      * @see findExtent()
0242      */
0243     QString findXmlId(KoTextEditor *cursor) const;
0244 
0245 
0246     /**
0247      * Find all of the statements which are
0248      * in context for a given cursor position.
0249      *
0250      * Rdf is also added to the returned model from external manifest.rdf
0251      * and other files which attach to the xml:id
0252      *
0253      * The depth parameter allows triple expansion, ie,
0254      *        depth=1   adds only triples which reference ?s ?p xml:id
0255      *        depth=2   adds references to statements in depth=1,
0256      *                  ie, ?s1 ?p2 ?s2 and ?s2 ?p xml:id
0257      * Because of the complexity, depth should be <=2 or you should use
0258      * a custom query.
0259      *
0260      * FIXME: The logical thing here would be to chain up.
0261      *   given a cursor in a table:cell, the Rdf for the containing
0262      *   text:p and text:meta elements should be returned too.
0263      *
0264      * Note that the returned model is owned by the caller, you must delete it.
0265      */
0266     QSharedPointer<Soprano::Model> findStatements(const QString &xmlid, int depth = 1);
0267     QSharedPointer<Soprano::Model> findStatements(KoTextEditor *handler, int depth = 1);
0268 
0269     /**
0270      * Add all the Rdf that is associated with the given xml:id
0271      */
0272     void addStatements(QSharedPointer<Soprano::Model> model, const QString &xmlid);
0273 
0274     /**
0275      * Find an inline Rdf object from the xml:id which
0276      * it has in the content.xml file
0277      */
0278     KoTextInlineRdf* findInlineRdfByID(const QString &xmlid) const;
0279 
0280     /**
0281      * Obtain a list of semantic objects of the given class, if any, for the Rdf
0282      * in the default model() or the one you optionally pass in.
0283      */
0284     QList< hKoRdfBasicSemanticItem > semanticItems(const QString &className, QSharedPointer< Soprano::Model > m = QSharedPointer<Soprano::Model>(0));
0285 
0286     /**
0287      * Create a SemanticItem subclass using its name from
0288      * classNames(). Useful for menus and other places that want to
0289      * allow the user to create new SemanticItem Objects.
0290      */
0291     hKoRdfBasicSemanticItem createSemanticItem(const QString &semanticClass, QObject *parent = 0) const;
0292 
0293     /**
0294      * This is used for triples that do not specify their xhtml:about
0295      * ie, the subject URI.
0296      */
0297     QString rdfInternalMetadataWithoutSubjectURI() const;
0298 
0299     /**
0300      * Soprano::Node that can be used as the model context for
0301      * statements which should be stored in the manifest.rdf file.
0302      */
0303     Soprano::Node manifestRdfNode() const;
0304 
0305     /**
0306      * Soprano::Node that can be used as the model context for
0307      * statements which were stored in the context.xml file.
0308      */
0309     Soprano::Node inlineRdfContext() const;
0310 
0311     /**
0312      * If model contains ?s ?p ?o
0313      * look for and add
0314      * ?s2 ?p2 ?s
0315      */
0316     void expandStatementsReferencingSubject(QSharedPointer<Soprano::Model> model) const;
0317 
0318     /**
0319      * If model contains ?s ?p ?o
0320      * look for and add
0321      * ?o ?p2 ?o2
0322      */
0323     void expandStatementsSubjectPointsTo(QSharedPointer<Soprano::Model> model) const;
0324 
0325     /**
0326      * Add n ?p ?o from m_model to model
0327      */
0328     void expandStatementsSubjectPointsTo(QSharedPointer<Soprano::Model> model, const Soprano::Node &n) const;
0329 
0330     /**
0331      * Rdf allows for linked lists to be serialized as a graph. This method will
0332      * ensure that all data from m_model for any lists that are started in 'model'
0333      * is copied into 'model'.
0334      *
0335      * Lists have the format
0336      * prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
0337      * ?id    rdf:first  ?value
0338      * ?id    rdf:rest   ?next1
0339      * ?next1 rdf:first  ?value2
0340      * ?next1 rdf:rest   ?nextN
0341      * ?nextN rdf:first  ?valueN
0342      * ?nextN rdf:rest   rdf:nil
0343      */
0344     void expandStatementsToIncludeRdfLists(QSharedPointer<Soprano::Model> model) const;
0345 
0346     /**
0347      * If model contains ?s ?p ?o
0348      * look for and add
0349      * ?s ?p3 ?o3
0350      */
0351     void expandStatementsToIncludeOtherPredicates(QSharedPointer<Soprano::Model> model) const;
0352 
0353     /**
0354      * One round of all expandStatements methods
0355      */
0356     void expandStatements(QSharedPointer<Soprano::Model> model) const;
0357 
0358     /**
0359      * FIXME? What does this do?
0360      */
0361     QAction * createInsertSemanticObjectReferenceAction(KoCanvasBase *host);
0362 
0363     /**
0364      * FIXME? What does this do?
0365      */
0366     QList<QAction *> createInsertSemanticObjectNewActions(KoCanvasBase *host);
0367 
0368     /**
0369      * Collect together the semantic item, stylehseet, xmlid of the
0370      * site to apply it at and the extent in the document (start,end)
0371      * of the semantic item. Used when applying stylesheets in bulk so
0372      * that all the sites can be collected and the QMap<int,reflowItem> map
0373      * will sort them in the order of start to end document position.
0374      *
0375      * @see insertReflow()
0376      * @see applyReflow()
0377      */
0378     struct reflowItem
0379     {
0380         hKoRdfSemanticItem m_si;
0381         hKoSemanticStylesheet m_ss;
0382         QString m_xmlid;
0383         QPair<int, int> m_extent;
0384 
0385         reflowItem(hKoRdfSemanticItem si, const QString &xmlid, hKoSemanticStylesheet ss, const QPair<int, int> &extent);
0386     };
0387 
0388     /**
0389      * Because applying a stylesheet to a semantic item could change
0390      * the length of the text showing the item in the document, it is
0391      * best to apply these stylesheets to semitems starting from the
0392      * end of the document. This is because any change in the length
0393      * of a semitem has no effect on all the other semitems that are
0394      * before it in the document. After we have applied all the
0395      * changes, the kwdoc will update the positions of all the
0396      * kotextmeta etc objects and they will once again be correct.
0397      * Doing things explicitly backwards is a huge efficiency gain
0398      * because no layout is needed on the document during our updates
0399      * because each update does not invalidate the positions of any
0400      * objects before the update in the document text.
0401      *
0402      * Call insertReflow() for all the items you want to apply a
0403      * stylesheet on and then applyReflow() with the built up
0404      * collection 'col' argument to will actually apply the
0405      * stylesheets starting from the semitem lowest in the document
0406      * and working backwards.
0407      *
0408      * @see applyReflow()
0409      */
0410     void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj, hKoSemanticStylesheet ss);
0411     void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj, const QString &sheetType, const QString &stylesheetName);
0412     void insertReflow(QMap<int, reflowItem> &col, hKoRdfSemanticItem obj);
0413     /**
0414      * @short Apply the stylesheets built up with insertReflow().
0415      *
0416      * @see insertReflow()
0417      */
0418     void applyReflow(const QMap<int, reflowItem> &col);
0419 
0420     //FIXME: this method also seems to be STATIC and why it has such second default param??
0421     /**
0422      * For debugging, output the model and a header string for identification
0423      */
0424     void dumpModel(const QString &msg, QSharedPointer<Soprano::Model> m = QSharedPointer<Soprano::Model>(0)) const;
0425 
0426 Q_SIGNALS:
0427     /**
0428      * Emitted when a new semanticItem is created so that dockers can
0429      * update themselves accordingly. It is expected that when
0430      * semanticObjectViewSiteUpdated is emitted the view will take care
0431      * of reflowing the semantic item using it's stylesheet.
0432      */
0433     void semanticObjectAdded(hKoRdfBasicSemanticItem item) const;
0434     void semanticObjectUpdated(hKoRdfBasicSemanticItem item) const;
0435     void semanticObjectViewSiteUpdated(hKoRdfBasicSemanticItem item, const QString &xmlid) const;
0436 
0437 public:
0438     void emitSemanticObjectAdded(hKoRdfBasicSemanticItem item) const;
0439     void emitSemanticObjectUpdated(hKoRdfBasicSemanticItem item);
0440     void emitSemanticObjectViewSiteUpdated(hKoRdfBasicSemanticItem item, const QString &xmlid);
0441     void emitSemanticObjectAddedConst(hKoRdfBasicSemanticItem const item) const;
0442 
0443     /**
0444      * You should use the KoRdfSemanticItem::userStylesheets() method instead of this one.
0445      * This is mainly an internal method to allow user stylesheets to be managed per document.
0446      */
0447     QList<hKoSemanticStylesheet> userStyleSheetList(const QString& className) const;
0448     void setUserStyleSheetList(const QString& className,const QList<hKoSemanticStylesheet>& l);
0449 
0450 
0451 private:
0452 
0453     /**
0454      * @see expandStatementsToIncludeRdfLists()
0455      */
0456     void expandStatementsToIncludeRdfListsRecurse(QSharedPointer<Soprano::Model> model,
0457             QList<Soprano::Statement> &addList,
0458             const Soprano::Node &n) const;
0459 
0460 
0461     /**
0462      * Soprano can give undesirable behaviour when loading two files
0463      * into the same model. When parsing the second Rdf file, the sane
0464      * genid1 numbers can be reused, leading to semantic errors on
0465      * bnodes. This method updates all the bnodes in 'm' to be new
0466      * ones created using m_model->createBlankNode(). bnode identity
0467      * is preserved for the model m. ie. genid2 and another genid2 in
0468      * m will be replaced with the same m_model->createBlankNode()
0469      * value. After calling this method, you can add all the
0470      * statements to 'm' and be assured that no bnodes in 'm' are
0471      * going to accidentially be the same as a bnode in m_model.
0472      */
0473     void freshenBNodes(QSharedPointer<Soprano::Model> m);
0474 
0475     /**
0476      * Used by loadOasis() to load Rdf from a particular external
0477      * Rdf/XML file.
0478      */
0479     bool loadRdf(KoStore *store, const Soprano::Parser *parser, const QString &fileName);
0480 
0481     /**
0482      * Used by saveOasis() to save Rdf to a the Rdf file nominated
0483      * with context. Note that this method can not be used to save to
0484      * content.xml, those Rdf statements must be saved as the
0485      * content.xml file is generated.
0486      */
0487     bool saveRdf(KoStore *store, KoXmlWriter *manifestWriter, const Soprano::Node &context) const;
0488 
0489 
0490     /**
0491      * idrefList queries soprano after loading and creates a list of all rdfid's that
0492      * where found in the manifest.rdf document. This list is used to make sure we do not
0493      * create more inline rdf objects than necessary
0494      * @return a list of xml-id's
0495      */
0496     QStringList idrefList() const;
0497 
0498 private:
0499 
0500     /**
0501      * Test whether a model is present that supports:
0502      * - context / graphs
0503      *  - querying on graphs
0504      *  - storage in memory.
0505      */
0506     bool backendIsSane();
0507 
0508     /// reimplemented
0509     virtual bool completeLoading(KoStore *store);
0510 
0511     /// reimplemented
0512     virtual bool completeSaving(KoStore *store, KoXmlWriter *manifestWriter, KoShapeSavingContext *context);
0513 
0514     KoDocumentRdfPrivate * const d;
0515 };
0516 
0517 #endif