[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - 10 commits - sfx2/source sw/inc sw/source

Ashod Nakashian (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 26 08:29:20 UTC 2019


 sfx2/source/doc/DocumentMetadataAccess.cxx  |   67 ++++++++++---
 sw/inc/editsh.hxx                           |   12 +-
 sw/inc/rdfhelper.hxx                        |   23 ++++
 sw/source/core/doc/DocumentTimerManager.cxx |    4 
 sw/source/core/doc/rdfhelper.cxx            |   87 +++++++++++++----
 sw/source/core/edit/edfcol.cxx              |  139 ++++++++++++++++------------
 sw/source/core/edit/edws.cxx                |   11 --
 sw/source/core/txtnode/ndtxt.cxx            |   11 +-
 8 files changed, 239 insertions(+), 115 deletions(-)

New commits:
commit ad9902f34dd0b5837ab518445ea9f3a24352738b
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Oct 3 05:53:28 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:41:02 2019 +0200

    sw: paragraph-sign: process signatures in one pass on loading
    
    This combines the metadata field restoration logic with
    validation/update of said field in one pass upon loading docs.
    This cuts down overheads and makes the code more readable.
    
    In addition, now that paragraph signature validation is quite
    cheap (separate commits), esp. when no signatures exist, we
    validate and update signatures (where applicable) when fields
    are updated.
    
    Change-Id: I4adcea579c591f9be457ed742d2cf54fa308163d
    Reviewed-on: https://gerrit.libreoffice.org/63008
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 4891dfb9f92b..01eee9f968ad 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -386,8 +386,11 @@ public:
     /// Validate all paragraph signatures.
     void ValidateAllParagraphSignatures(bool updateDontRemove);
 
-    /// Restore the metadata fields, if missing, from the RDF metadata.
-    void RestoreMetadataFields();
+    /// Restore the metadata fields, if missing, from the RDF metadata
+    /// and validate the signatures and update the signature metadata fields.
+    /// Needed since deleting the metadata field doesn't remove the RDF
+    /// and editing docs using software that don't support paragraph signing.
+    void RestoreMetadataFieldsAndValidateParagraphSignatures();
 
     /// Ensure that the classification of the doc is never lower than
     /// the paragraph with the highest classification.
diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index c021276ed680..c57cfe65038c 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -34,6 +34,7 @@
 #include <docfld.hxx>
 #include <fldbas.hxx>
 #include <comphelper/lok.hxx>
+#include <editsh.hxx>
 
 namespace sw
 {
@@ -191,6 +192,9 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
         m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);  // Tables
         m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();  // References
 
+        // Validate and update the paragraph signatures.
+        m_rDoc.GetEditShell()->ValidateAllParagraphSignatures(true);
+
         pTmpRoot->EndAllAction();
 
         pShell->LockView( bOldLockView );
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 191c9c70ffcf..ce08b170c986 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -1896,7 +1896,7 @@ uno::Reference<text::XTextField> lcl_GetParagraphMetadataFieldAtIndex(const SwDo
     return xTextField;
 }
 
-void SwEditShell::RestoreMetadataFields()
+void SwEditShell::RestoreMetadataFieldsAndValidateParagraphSignatures()
 {
     SwDocShell* pDocShell = GetDoc()->GetDocShell();
     if (!pDocShell || !IsParagraphSignatureValidationEnabled())
@@ -2022,6 +2022,7 @@ void SwEditShell::RestoreMetadataFields()
                 }
             }
 
+            lcl_ValidateParagraphSignatures(GetDoc(), xParagraph, true); // Validate and Update signatures.
         }
         catch (const std::exception&)
         {
@@ -2115,7 +2116,7 @@ OUString lcl_GetHighestClassificationParagraphClass(SwPaM* pCursor)
     while (xParagraphs->hasMoreElements())
     {
         uno::Reference<text::XTextContent> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY);
-        OUString sCurrentClass = lcl_GetParagraphClassification(aHelper, aKeyCreator, xModel, xParagraph);
+        const OUString sCurrentClass = lcl_GetParagraphClassification(aHelper, aKeyCreator, xModel, xParagraph);
         sHighestClass = aHelper.GetHigherClass(sHighestClass, sCurrentClass);
     }
 
@@ -2128,7 +2129,7 @@ void SwEditShell::ClassifyDocPerHighestParagraphClass()
     if (!pDocShell)
         return;
 
-    // bail out as early as possible if we don't have paragraph classification
+    // Bail out as early as possible if we don't have paragraph classification.
     if (!SwRDFHelper::hasMetadataGraph(pDocShell->GetBaseModel(), MetaNS))
         return;
 
diff --git a/sw/source/core/edit/edws.cxx b/sw/source/core/edit/edws.cxx
index d9ce2329e225..eae129280c10 100644
--- a/sw/source/core/edit/edws.cxx
+++ b/sw/source/core/edit/edws.cxx
@@ -17,11 +17,12 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <editsh.hxx>
+
 #include <officecfg/Office/Common.hxx>
 #include <unotools/configmgr.hxx>
 #include <vcl/window.hxx>
 
-#include <editsh.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
 #include <IDocumentState.hxx>
@@ -51,12 +52,8 @@ SwEditShell::SwEditShell( SwDoc& rDoc, vcl::Window *pWindow, const SwViewOption
         GetDoc()->GetIDocumentUndoRedo().DoUndo(true);
     }
 
-    // Restore the tscp metadata fields
-    RestoreMetadataFields();
-
-    // Update the paragraph signatures.
-    // Since this ctor is called only on creating/loading the doc, we validate once only.
-    ValidateAllParagraphSignatures(true);
+    // Restore the paragraph metadata fields and validate signatures.
+    RestoreMetadataFieldsAndValidateParagraphSignatures();
 }
 
 SwEditShell::~SwEditShell() // USED
commit 10a0693a60d11cfd2401f9f96041bc3d5d7c4c5b
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Oct 3 05:49:51 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:41:01 2019 +0200

    sw: paragraph-sign: avoid re-validating paragraphs when classifying
    
    When setting the classification watermark, every edit to the document
    is triggering a re-validation of signatures, which is excessive and
    excessively expensive.
    
    Change-Id: I7808877263f553a871f2c31856da1a2f9e50c4bb
    Reviewed-on: https://gerrit.libreoffice.org/63007
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index aaf7a80315a4..191c9c70ffcf 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -2155,6 +2155,12 @@ void SwEditShell::ClassifyDocPerHighestParagraphClass()
 
     const SfxClassificationPolicyType eHighestClassType = SfxClassificationHelper::stringToPolicyType(sHighestClass);
 
+    // Prevent paragraph signature validation since the below changes (f.e. watermarking) are benign.
+    const bool bOldValidationFlag = SetParagraphSignatureValidation(false);
+    comphelper::ScopeGuard const g([this, bOldValidationFlag]() {
+        SetParagraphSignatureValidation(bOldValidationFlag);
+    });
+
     // Check the origin, if "manual" (created via advanced classification dialog),
     // then we just need to set the category name.
     if (sfx::getCreationOriginProperty(xPropertyContainer, aKeyCreator) == sfx::ClassificationCreationOrigin::MANUAL)
commit ffc9efb5c770a674c781bfedb3b91e912b6d0136
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Oct 3 05:47:49 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:41:00 2019 +0200

    sw: paragraph-sign: skip invalid graph names
    
    Change-Id: Iaff61723497466521eddb2333656981f976d3fa6
    Reviewed-on: https://gerrit.libreoffice.org/63006
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/source/core/doc/rdfhelper.cxx b/sw/source/core/doc/rdfhelper.cxx
index d1fb7d4dbf4f..ff77293639cc 100644
--- a/sw/source/core/doc/rdfhelper.cxx
+++ b/sw/source/core/doc/rdfhelper.cxx
@@ -73,6 +73,9 @@ SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel
     for (const uno::Reference<rdf::XURI>& xGraphName : rGraphNames)
     {
         uno::Reference<rdf::XNamedGraph> xGraph = xRepo->getGraph(xGraphName);
+        if (!xGraph.is())
+            continue;
+
         uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(
             xSubject, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
         while (xStatements->hasMoreElements())
commit 89c351a2610cc24720f391cf933f8af170de03ed
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Tue Oct 2 06:02:39 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:41:00 2019 +0200

    sw: paragraph-sign: formatting
    
    Change-Id: I9bf1b58aa6e18202a5f7eba010cc5b914e1d33d4
    Reviewed-on: https://gerrit.libreoffice.org/63005
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 48eb39da6a80..aaf7a80315a4 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -354,14 +354,16 @@ SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel
     SignatureDescr aDescr;
     aDescr.msId = sFieldId;
 
+    const OUString prefix = ParagraphSignatureRDFNamespace + sFieldId;
     const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xParagraph);
-    const auto itSig = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureDigestRDFName);
+
+    const auto itSig = aStatements.find(prefix + ParagraphSignatureDigestRDFName);
     aDescr.msSignature = (itSig != aStatements.end() ? itSig->second : OUString());
 
-    const auto itDate = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureDateRDFName);
+    const auto itDate = aStatements.find(prefix + ParagraphSignatureDateRDFName);
     aDescr.msDate = (itDate != aStatements.end() ? itDate->second : OUString());
 
-    const auto itUsage = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureUsageRDFName);
+    const auto itUsage = aStatements.find(prefix + ParagraphSignatureUsageRDFName);
     aDescr.msUsage = (itUsage != aStatements.end() ? itUsage->second : OUString());
 
     return aDescr;
@@ -371,14 +373,16 @@ SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel
                                      const uno::Reference<css::text::XTextContent>& xParagraph,
                                      const uno::Reference<css::text::XTextField>& xField)
 {
-    const std::pair<OUString, OUString> pair = lcl_getRDF(xModel, xField, ParagraphSignatureIdRDFName);
-    return (!pair.second.isEmpty() ? lcl_getSignatureDescr(xModel, xParagraph, pair.second) : SignatureDescr());
+    const OUString sFieldId = lcl_getRDF(xModel, xField, ParagraphSignatureIdRDFName).second;
+    if (!sFieldId.isEmpty())
+        return lcl_getSignatureDescr(xModel, xParagraph, sFieldId);
+
+    return SignatureDescr();
 }
 
 /// Validate and create the signature field display text from the fields.
-std::pair<bool, OUString>
-lcl_MakeParagraphSignatureFieldText(const SignatureDescr& aDescr,
-                                    const OString& utf8Text)
+std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const SignatureDescr& aDescr,
+                                                              const OString& utf8Text)
 {
     OUString msg = SwResId(STR_INVALID_SIGNATURE);
     bool valid = false;
@@ -394,7 +398,8 @@ lcl_MakeParagraphSignatureFieldText(const SignatureDescr& aDescr,
             const std::vector<unsigned char> sig(svl::crypto::DecodeHexString(encSignature));
             SignatureInformation aInfo(0);
             valid = svl::crypto::Signing::Verify(data, false, sig, aInfo);
-            valid = valid && aInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+            valid = valid
+                    && aInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
 
             msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.ouSubject + ", ";
             msg += aDescr.msDate;
@@ -406,7 +411,6 @@ lcl_MakeParagraphSignatureFieldText(const SignatureDescr& aDescr,
     return std::make_pair(valid, msg);
 }
 
-
 /// Validate and return validation result and signature field display text.
 std::pair<bool, OUString>
 lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel,
@@ -422,11 +426,10 @@ lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel,
 OUString lcl_getNextSignatureId(const uno::Reference<frame::XModel>& xModel,
                                 const uno::Reference<text::XTextContent>& xParagraph)
 {
-    const std::pair<OUString, OUString> pair = lcl_getRDF(xModel, xParagraph, ParagraphSignatureLastIdRDFName);
-    return OUString::number(!pair.second.isEmpty() ? pair.second.toInt32() + 1 : 1);
+    const OUString sFieldId = lcl_getRDF(xModel, xParagraph, ParagraphSignatureLastIdRDFName).second;
+    return OUString::number(!sFieldId.isEmpty() ? sFieldId.toInt32() + 1 : 1);
 }
 
-
 /// Creates and inserts Paragraph Signature Metadata field and creates the RDF entry
 uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Reference<frame::XModel>& xModel,
                                                               const uno::Reference<text::XTextContent>& xParagraph,
@@ -460,10 +463,11 @@ uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Referen
 
     // Now set the RDF on the paragraph, since that's what is preserved in .doc(x).
     const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY);
+    const OUString prefix = ParagraphSignatureRDFNamespace + sId;
     SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureLastIdRDFName, sId);
-    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureDigestRDFName, signature);
-    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureUsageRDFName, usage);
-    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureDateRDFName, rBuffer.makeStringAndClear());
+    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureDigestRDFName, signature);
+    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureUsageRDFName, usage);
+    SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureDateRDFName, rBuffer.makeStringAndClear());
 
     return xField;
 }
@@ -506,8 +510,9 @@ bool lcl_UpdateParagraphSignatureField(SwDoc* pDoc,
                                        const uno::Reference<css::text::XTextField>& xField,
                                        const OString& utf8Text)
 {
-    const std::pair<bool, OUString> res = lcl_MakeParagraphSignatureFieldText(xModel, xParagraph, xField, utf8Text);
-    return lcl_DoUpdateParagraphSignatureField(pDoc, xField, res.second);
+    const OUString sDisplayText
+        = lcl_MakeParagraphSignatureFieldText(xModel, xParagraph, xField, utf8Text).second;
+    return lcl_DoUpdateParagraphSignatureField(pDoc, xField, sDisplayText);
 }
 
 void lcl_RemoveParagraphMetadataField(const uno::Reference<css::text::XTextField>& xField)
commit 25446d1c7d021ba99201f36b04d59c29c85b7733
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Tue Oct 2 05:20:38 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:59 2019 +0200

    sw: paragraph-sign: validate current SwTextNode directly
    
    When invoking undo, it turns out that the cursor position
    is updated after the text modification, which triggers the
    paragraph signature validation. Relying on the cursor
    position, then, results in the wrong (previous) paragraph
    to be validated (if the undo is in a different paragraph).
    
    Since we have the correct SwTextNode when it's modified
    (due to undo or otherwise), there is no reason why
    we shouldn't use it and try to deduce it from the cursor.
    
    Change-Id: I4c3283d59738988dcc1c592a9f3ef2c818ce675d
    Reviewed-on: https://gerrit.libreoffice.org/63004
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 70250a85ac6c..4891dfb9f92b 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -377,7 +377,10 @@ public:
     /// Sign the paragraph at the cursor.
     void SignParagraph();
 
-    /// Validate current paragraph signatures, if any, at the cursor start.
+    /// Validate the paragraph signatures, if any, of the current text node.
+    void ValidateParagraphSignatures(SwTextNode* pNode, bool updateDontRemove);
+
+    /// Validate the current paragraph signatures, if any, at the cursor start.
     void ValidateCurrentParagraphSignatures(bool updateDontRemove);
 
     /// Validate all paragraph signatures.
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index d95aea806c8f..48eb39da6a80 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -1805,16 +1805,13 @@ void SwEditShell::SignParagraph()
     GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::PARA_SIGN_ADD, nullptr);
 }
 
-void SwEditShell::ValidateCurrentParagraphSignatures(bool updateDontRemove)
+void SwEditShell::ValidateParagraphSignatures(SwTextNode* pNode, bool updateDontRemove)
 {
-    SwDocShell* pDocShell = GetDoc()->GetDocShell();
-    if (!pDocShell || !GetCursor() || !GetCursor()->Start() || !IsParagraphSignatureValidationEnabled())
+    if (!pNode || !IsParagraphSignatureValidationEnabled())
         return;
 
-    SwPaM* pPaM = GetCursor();
-    const SwPosition* pPosStart = pPaM->Start();
-    SwTextNode* pNode = pPosStart->nNode.GetNode().GetTextNode();
-    if (!pNode)
+    // Table text signing is not supported.
+    if (pNode->FindTableNode() != nullptr)
         return;
 
     // Prevent recursive validation since this is triggered on node updates, which we do below.
@@ -1823,12 +1820,20 @@ void SwEditShell::ValidateCurrentParagraphSignatures(bool updateDontRemove)
             SetParagraphSignatureValidation(bOldValidationFlag);
         });
 
-    // Table text signing is not supported.
-    if (pNode->FindTableNode() != nullptr)
+    uno::Reference<text::XTextContent> xParentText = SwXParagraph::CreateXParagraph(*GetDoc(), pNode);
+    lcl_ValidateParagraphSignatures(GetDoc(), xParentText, updateDontRemove);
+}
+
+void SwEditShell::ValidateCurrentParagraphSignatures(bool updateDontRemove)
+{
+    SwDocShell* pDocShell = GetDoc()->GetDocShell();
+    if (!pDocShell || !GetCursor() || !GetCursor()->Start() || !IsParagraphSignatureValidationEnabled())
         return;
 
-    uno::Reference<text::XTextContent> xParentText = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode);
-    lcl_ValidateParagraphSignatures(GetDoc(), xParentText, updateDontRemove);
+    SwPaM* pPaM = GetCursor();
+    const SwPosition* pPosStart = pPaM->Start();
+    SwTextNode* pNode = pPosStart->nNode.GetNode().GetTextNode();
+    ValidateParagraphSignatures(pNode, updateDontRemove);
 }
 
 void SwEditShell::ValidateAllParagraphSignatures(bool updateDontRemove)
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index c603ebdd40d4..9797c60b4441 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -1214,7 +1214,7 @@ void SwTextNode::Update(
     // Update the paragraph signatures.
     if (SwEditShell* pEditShell = GetDoc()->GetEditShell())
     {
-        pEditShell->ValidateCurrentParagraphSignatures(true);
+        pEditShell->ValidateParagraphSignatures(this, true);
     }
 
     // Inform LOK clients about change in position of redlines (if any)
commit 9ae364330ddbc7cec836d42221ebc9f7b4c40240
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Oct 1 07:56:14 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:59 2019 +0200

    sw: paragraph-sign: get graph-names only once
    
    And reduce other overheads to make the paragraph
    signature validation significantly faster.
    
    Change-Id: I631bd0f15200bb8f0b85b40c0d4819a7bc4d562e
    Reviewed-on: https://gerrit.libreoffice.org/63003
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index f79fc443199e..d95aea806c8f 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -538,6 +538,7 @@ uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const uno:
     if (!xTextPortionEnumerationAccess.is())
         return xTextField;
 
+    // Enumerate text portions to find metadata fields. This is expensive, best to enumerate fields only.
     uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration();
     while (xTextPortions->hasMoreElements())
     {
@@ -555,7 +556,6 @@ uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const uno:
         uno::Reference<text::XTextField> xField(xServiceInfo, uno::UNO_QUERY);
         if (lcl_IsParagraphClassificationField(xModel, xField, sKey))
         {
-            uno::Reference<css::text::XTextRange> xText(xField, uno::UNO_QUERY);
             xTextField = xField;
             break;
         }
@@ -1151,10 +1151,6 @@ void lcl_ApplyParagraphClassification(SwDoc* pDoc,
     if (!xNodeSubject.is())
         return;
 
-    uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
-
-    sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
-
     // Remove all paragraph classification fields.
     for (;;)
     {
@@ -1177,13 +1173,14 @@ void lcl_ApplyParagraphClassification(SwDoc* pDoc,
                                             { return rResult.meType == svx::ClassificationType::PARAGRAPH; }),
                                   aResults.end());
 
+    sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
     std::vector<OUString> aFieldNames;
     for (size_t nIndex = 0; nIndex < aResults.size(); ++nIndex)
     {
         const svx::ClassificationResult& rResult = aResults[nIndex];
 
         const bool isLast = nIndex == 0;
-        const bool isFirst = nIndex == aResults.size() - 1;
+        const bool isFirst = (nIndex == aResults.size() - 1);
         OUString sKey;
         OUString sValue = rResult.msName;
         switch (rResult.meType)
@@ -1910,19 +1907,23 @@ void SwEditShell::RestoreMetadataFields()
     uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration();
     if (!xParagraphs.is())
         return;
+
+    static const OUString sBlank("");
+    const sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
+    const css::uno::Sequence<css::uno::Reference<rdf::XURI>> aGraphNames = SwRDFHelper::getGraphNames(xModel, MetaNS);
+
     while (xParagraphs->hasMoreElements())
     {
         uno::Reference<text::XTextContent> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY);
 
-        std::map<OUString, SignatureDescr> aSignatures;
-        std::vector<svx::ClassificationResult> aResults;
-
         try
         {
-            const sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
-            const OUString sBlank("");
+            const css::uno::Reference<css::rdf::XResource> xSubject(xParagraph, uno::UNO_QUERY);
+            const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, aGraphNames, xSubject);
 
-            const OUString sFieldNames = lcl_getRDF(xModel, xParagraph, ParagraphClassificationFieldNamesRDFName).second;
+            const auto it = aStatements.find(ParagraphClassificationFieldNamesRDFName);
+            const OUString sFieldNames = (it != aStatements.end() ? it->second : sBlank);
+            std::vector<svx::ClassificationResult> aResults;
             if (!sFieldNames.isEmpty())
             {
                 // Order the fields
@@ -1932,9 +1933,10 @@ void SwEditShell::RestoreMetadataFields()
                     const OUString sCurFieldName = sFieldNames.getToken(0, '/', nIndex);
                     if (sCurFieldName.isEmpty())
                         break;
-                    std::pair<OUString, OUString> fieldNameValue = lcl_getRDF(xModel, xParagraph, sCurFieldName);
-                    const OUString sName = fieldNameValue.first;
-                    const OUString sValue = fieldNameValue.second;
+
+                    const auto it2 = aStatements.find(sCurFieldName);
+                    const OUString sName = (it2 != aStatements.end() ? it->first : sBlank);
+                    const OUString sValue = (it2 != aStatements.end() ? it->second : sBlank);
 
                     if (aKeyCreator.isMarkingTextKey(sName))
                     {
@@ -1942,14 +1944,14 @@ void SwEditShell::RestoreMetadataFields()
                     }
                     else if (aKeyCreator.isCategoryNameKey(sName))
                     {
-                        const std::pair<OUString, OUString> pairAbbr = lcl_getRDF(xModel, xParent, ParagraphClassificationAbbrRDFName);
-                        const OUString sAbbreviatedName = (!pairAbbr.second.isEmpty() ? pairAbbr.second : sValue);
+                        const auto it3 = aStatements.find(ParagraphClassificationAbbrRDFName);
+                        const OUString sAbbreviatedName = (it3 != aStatements.end() && !it3->second.isEmpty() ? it3->second : sValue);
                         aResults.push_back({ svx::ClassificationType::CATEGORY, sValue, sAbbreviatedName, sBlank });
                     }
                     else if (aKeyCreator.isCategoryIdentifierKey(sName))
                     {
-                        const std::pair<OUString, OUString> pairAbbr = lcl_getRDF(xModel, xParent, ParagraphClassificationAbbrRDFName);
-                        const OUString sAbbreviatedName = (!pairAbbr.second.isEmpty() ? pairAbbr.second : sValue);
+                        const auto it3 = aStatements.find(ParagraphClassificationAbbrRDFName);
+                        const OUString sAbbreviatedName = (it3 != aStatements.end() && !it3->second.isEmpty() ? it3->second : sValue);
                         aResults.push_back({ svx::ClassificationType::CATEGORY, sBlank, sAbbreviatedName, sValue });
                     }
                     else if (aKeyCreator.isMarkingKey(sName))
@@ -1964,21 +1966,23 @@ void SwEditShell::RestoreMetadataFields()
                 while (nIndex >= 0);
             }
 
+            // Update classification based on results.
             lcl_ApplyParagraphClassification(GetDoc(), xModel, xParagraph, aResults);
 
             // Get Signatures
+            std::map<OUString, SignatureDescr> aSignatures;
             for (const auto& pair : lcl_getRDFStatements(xModel, xParagraph))
             {
-                const OUString sName = pair.first;
-                const OUString sValue = pair.second;
+                const OUString& sName = pair.first;
                 if (sName.startsWith(ParagraphSignatureRDFNamespace))
                 {
-                    OUString sSuffix = sName.copy(ParagraphSignatureRDFNamespace.getLength());
-                    sal_Int32 index = sSuffix.indexOf(":");
+                    const OUString sSuffix = sName.copy(ParagraphSignatureRDFNamespace.getLength());
+                    const sal_Int32 index = sSuffix.indexOf(":");
                     if (index >= 0)
                     {
-                        OUString id = sSuffix.copy(0, index);
-                        OUString type = sSuffix.copy(index);
+                        const OUString id = sSuffix.copy(0, index);
+                        const OUString type = sSuffix.copy(index);
+                        const OUString& sValue = pair.second;
                         if (type == ParagraphSignatureDateRDFName)
                             aSignatures[id].msDate = sValue;
                         else if (type == ParagraphSignatureUsageRDFName)
@@ -2007,6 +2011,7 @@ void SwEditShell::RestoreMetadataFields()
                     lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xParagraph, xField, utf8Text);
                 }
             }
+
         }
         catch (const std::exception&)
         {
@@ -2070,8 +2075,7 @@ OUString lcl_GetParagraphClassification(SfxClassificationHelper & rHelper, sfx::
     xTextField = lcl_FindParagraphClassificationField(xModel, xParagraph, rKeyCreator.makeCategoryNameKey());
     if (xTextField.is())
     {
-        const std::pair<OUString, OUString> rdfValuePair = lcl_getRDF(xModel, xTextField, ParagraphClassificationNameRDFName);
-        return rdfValuePair.second;
+        return lcl_getRDF(xModel, xTextField, ParagraphClassificationNameRDFName).second;
     }
 
     return OUString();
commit f29f873d8e638d566f53f9ac5712e49910ee4094
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sun Oct 28 14:44:34 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:58 2019 +0200

    paragraph-sign: exception-safe metadata graph enumeration
    
    Metadata graph enumeration can throw from a number
    functions and break things in horrible ways.
    Here we sanitize against the most egregious offenders,
    but not all possible sources.
    
    Change-Id: I40e006ea433dd7274d4fa08f3e8f8507680ef2f4
    Reviewed-on: https://gerrit.libreoffice.org/63009
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/inc/rdfhelper.hxx b/sw/inc/rdfhelper.hxx
index 149a2ed47529..03733a39d32b 100644
--- a/sw/inc/rdfhelper.hxx
+++ b/sw/inc/rdfhelper.hxx
@@ -26,6 +26,7 @@ namespace com { namespace sun { namespace star {
         class XModel;
     }
     namespace rdf {
+        class XDocumentMetadataAccess;
         class XResource;
         class XURI;
     }
@@ -37,6 +38,11 @@ class SW_DLLPUBLIC SwRDFHelper
 public:
     /// Gets all graph-names in RDF of a given type.
     static css::uno::Sequence<css::uno::Reference<css::rdf::XURI>>
+    getGraphNames(const css::uno::Reference<css::rdf::XDocumentMetadataAccess>& xDocumentMetadataAccess,
+                  const css::uno::Reference<css::rdf::XURI>& xType);
+
+    /// Gets all graph-names in RDF of a given type.
+    static css::uno::Sequence<css::uno::Reference<css::rdf::XURI>>
     getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType);
 
     /// Gets all (XResource, key, value) statements in RDF graphs given the graph-names.
diff --git a/sw/source/core/doc/rdfhelper.cxx b/sw/source/core/doc/rdfhelper.cxx
index 29e9e8dcf230..d1fb7d4dbf4f 100644
--- a/sw/source/core/doc/rdfhelper.cxx
+++ b/sw/source/core/doc/rdfhelper.cxx
@@ -23,15 +23,40 @@
 
 using namespace com::sun::star;
 
+css::uno::Sequence<css::uno::Reference<css::rdf::XURI>> SwRDFHelper::getGraphNames(
+    const css::uno::Reference<rdf::XDocumentMetadataAccess>& xDocumentMetadataAccess,
+    const css::uno::Reference<rdf::XURI>& xType)
+{
+    try
+    {
+        return xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    }
+    catch (const uno::RuntimeException&)
+    {
+        return uno::Sequence<uno::Reference<rdf::XURI>>();
+    }
+}
+
 css::uno::Sequence<uno::Reference<css::rdf::XURI>>
 SwRDFHelper::getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel,
                            const OUString& rType)
 {
-    uno::Reference<uno::XComponentContext> xComponentContext(
-        comphelper::getProcessComponentContext());
-    uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
-    uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    return xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    try
+    {
+        uno::Reference<uno::XComponentContext> xComponentContext(
+            comphelper::getProcessComponentContext());
+        // rdf::URI::create may fail with type: com.sun.star.uno.DeploymentException
+        // message: component context fails to supply service com.sun.star.rdf.URI of type com.sun.star.rdf.XURI
+        // context: cppu::ComponentContext
+        uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
+        uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel,
+                                                                             uno::UNO_QUERY);
+        return getGraphNames(xDocumentMetadataAccess, xType);
+    }
+    catch (const ::css::uno::Exception&)
+    {
+        return uno::Sequence<uno::Reference<rdf::XURI>>();
+    }
 }
 
 std::map<OUString, OUString>
@@ -76,7 +101,7 @@ void SwRDFHelper::addStatement(const css::uno::Reference<css::frame::XModel>& xM
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     uno::Reference<rdf::XURI> xGraphName;
     if (aGraphNames.hasElements())
         xGraphName = aGraphNames[0];
@@ -96,8 +121,7 @@ bool SwRDFHelper::hasMetadataGraph(const css::uno::Reference<css::frame::XModel>
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
-    return aGraphNames.hasElements();
+    return getGraphNames(xDocumentMetadataAccess, xType).hasElements();
 }
 
 void SwRDFHelper::removeStatement(const css::uno::Reference<css::frame::XModel>& xModel,
@@ -108,7 +132,7 @@ void SwRDFHelper::removeStatement(const css::uno::Reference<css::frame::XModel>&
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     if (!aGraphNames.hasElements())
         return;
 
@@ -125,7 +149,7 @@ void SwRDFHelper::clearStatements(const css::uno::Reference<css::frame::XModel>&
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     if (!aGraphNames.hasElements())
         return;
 
@@ -152,7 +176,7 @@ void SwRDFHelper::cloneStatements(const css::uno::Reference<css::frame::XModel>&
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xSrcModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     if (!aGraphNames.hasElements())
         return;
 
@@ -188,7 +212,7 @@ void SwRDFHelper::removeTextNodeStatement(const OUString& rType, SwTextNode& rTe
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(rTextNode.GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     if (!aGraphNames.hasElements())
         return;
 
@@ -205,7 +229,7 @@ void SwRDFHelper::updateTextNodeStatement(const OUString& rType, const OUString&
     uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(rTextNode.GetDoc()->GetDocShell()->GetBaseModel(), uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType);
     uno::Reference<rdf::XURI> xGraphName;
     if (aGraphNames.hasElements())
     {
commit d5c9288e00cf39292d077d58be550af566b779ac
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Oct 1 07:22:00 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:57 2019 +0200

    sw: rdf: Split graph-name lookup from getStatement
    
    The graph-name lookup is significantly costly (compared
    to the statement lookup, esp. when no statements exist).
    Luckily, the graph-names do not change often and in the
    course of enumerating all paragraphs (as happens for
    paragraph-signature validation) it doesn't change at all.
    
    This split allows for doing the graph-name lookup only
    once and also allows for passing custom graph-names
    directly, if we know them already.
    
    Change-Id: I75425df201becb41105ba1fa6ba580af202d035c
    Reviewed-on: https://gerrit.libreoffice.org/63002
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/inc/rdfhelper.hxx b/sw/inc/rdfhelper.hxx
index 5ec56b8a1935..149a2ed47529 100644
--- a/sw/inc/rdfhelper.hxx
+++ b/sw/inc/rdfhelper.hxx
@@ -17,6 +17,7 @@
 #include "swdllapi.h"
 
 #include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
 
 class SwTextNode;
 
@@ -26,6 +27,7 @@ namespace com { namespace sun { namespace star {
     }
     namespace rdf {
         class XResource;
+        class XURI;
     }
 }}}
 
@@ -33,11 +35,20 @@ namespace com { namespace sun { namespace star {
 class SW_DLLPUBLIC SwRDFHelper
 {
 public:
+    /// Gets all graph-names in RDF of a given type.
+    static css::uno::Sequence<css::uno::Reference<css::rdf::XURI>>
+    getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType);
+
+    /// Gets all (XResource, key, value) statements in RDF graphs given the graph-names.
+    static std::map<OUString, OUString>
+    getStatements(const css::uno::Reference<css::frame::XModel>& xModel,
+                  const css::uno::Sequence<css::uno::Reference<css::rdf::XURI>>& rGraphNames,
+                  const css::uno::Reference<css::rdf::XResource>& xSubject);
 
     /// Gets all (XResource, key, value) statements in RDF graphs of type rType.
-    static std::map<OUString, OUString> getStatements(const css::uno::Reference<css::frame::XModel>& xModel,
-                                                      const OUString& rType,
-                                                      const css::uno::Reference<css::rdf::XResource>& xSubject);
+    static std::map<OUString, OUString>
+    getStatements(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType,
+                  const css::uno::Reference<css::rdf::XResource>& xSubject);
 
     /// Add an (XResource, key, value) statement in the graph of type rType -- or if it does not exist, create a graph at rPath first.
     static void addStatement(const css::uno::Reference<css::frame::XModel>& xModel,
diff --git a/sw/source/core/doc/rdfhelper.cxx b/sw/source/core/doc/rdfhelper.cxx
index 8e8c78d90313..29e9e8dcf230 100644
--- a/sw/source/core/doc/rdfhelper.cxx
+++ b/sw/source/core/doc/rdfhelper.cxx
@@ -23,26 +23,36 @@
 
 using namespace com::sun::star;
 
-std::map<OUString, OUString> SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel,
-                                                        const OUString& rType,
-                                                        const css::uno::Reference<css::rdf::XResource>& xSubject)
+css::uno::Sequence<uno::Reference<css::rdf::XURI>>
+SwRDFHelper::getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel,
+                           const OUString& rType)
 {
-    std::map<OUString, OUString> aRet;
-
-    uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    uno::Reference<uno::XComponentContext> xComponentContext(
+        comphelper::getProcessComponentContext());
     uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType);
     uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
-    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
-    if (!aGraphNames.hasElements())
+    return xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+}
+
+std::map<OUString, OUString>
+SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel,
+                           const uno::Sequence<uno::Reference<css::rdf::XURI>>& rGraphNames,
+                           const css::uno::Reference<css::rdf::XResource>& xSubject)
+{
+    std::map<OUString, OUString> aRet;
+    if (!rGraphNames.hasElements())
         return aRet;
 
-    for (const uno::Reference<rdf::XURI>& xGraphName : aGraphNames)
+    uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY);
+    const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository();
+    for (const uno::Reference<rdf::XURI>& xGraphName : rGraphNames)
     {
-        uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName);
-        uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(xSubject, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
+        uno::Reference<rdf::XNamedGraph> xGraph = xRepo->getGraph(xGraphName);
+        uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(
+            xSubject, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
         while (xStatements->hasMoreElements())
         {
-            rdf::Statement aStatement = xStatements->nextElement().get<rdf::Statement>();
+            const rdf::Statement aStatement = xStatements->nextElement().get<rdf::Statement>();
             aRet[aStatement.Predicate->getStringValue()] = aStatement.Object->getStringValue();
         }
     }
@@ -50,6 +60,14 @@ std::map<OUString, OUString> SwRDFHelper::getStatements(const css::uno::Referenc
     return aRet;
 }
 
+std::map<OUString, OUString>
+SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel,
+                           const OUString& rType,
+                           const css::uno::Reference<css::rdf::XResource>& xSubject)
+{
+    return getStatements(xModel, getGraphNames(xModel, rType), xSubject);
+}
+
 void SwRDFHelper::addStatement(const css::uno::Reference<css::frame::XModel>& xModel,
                                const OUString& rType, const OUString& rPath,
                                const css::uno::Reference<css::rdf::XResource>& xSubject,
commit b6a16d2242cbee533ef46dd171a89ddd44f3af62
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Mon Oct 1 07:03:47 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:56 2019 +0200

    sfx2: Combine metadata graph lookup and filtering
    
    The graph lookup is suprisingly costly and so is
    filtering. By specializing the lookup with filtering
    the logic is more readable and slightly faster (~35%
    in debug build).
    
    Change-Id: Id35a562c76a84a81362f47b61ed67fb74d0a6dc7
    Reviewed-on: https://gerrit.libreoffice.org/63001
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sfx2/source/doc/DocumentMetadataAccess.cxx b/sfx2/source/doc/DocumentMetadataAccess.cxx
index bf765366e27f..dcdc3084187c 100644
--- a/sfx2/source/doc/DocumentMetadataAccess.cxx
+++ b/sfx2/source/doc/DocumentMetadataAccess.cxx
@@ -411,6 +411,48 @@ isPartOfType(struct DocumentMetadataAccess_Impl const & i_rImpl,
     }
 }
 
+static ::std::vector<uno::Reference<rdf::XURI>>
+getAllParts(struct DocumentMetadataAccess_Impl const& i_rImpl,
+            const uno::Reference<rdf::XURI>& i_xType)
+{
+    ::std::vector<uno::Reference<rdf::XURI>> ret;
+    try
+    {
+        const uno::Reference<container::XEnumeration> xEnum(
+            i_rImpl.m_xManifest->getStatements(i_rImpl.m_xBaseURI.get(),
+                                               getURI<rdf::URIs::PKG_HASPART>(i_rImpl.m_xContext),
+                                               nullptr),
+            uno::UNO_SET_THROW);
+        while (xEnum->hasMoreElements())
+        {
+            rdf::Statement stmt;
+            if (!(xEnum->nextElement() >>= stmt))
+            {
+                throw uno::RuntimeException();
+            }
+            const uno::Reference<rdf::XURI> xPart(stmt.Object, uno::UNO_QUERY);
+            if (!xPart.is())
+                continue;
+
+            const uno::Reference<container::XEnumeration> xEnum2(
+                i_rImpl.m_xManifest->getStatements(
+                    xPart.get(), getURI<rdf::URIs::RDF_TYPE>(i_rImpl.m_xContext), i_xType.get()),
+                uno::UNO_SET_THROW);
+            if (xEnum2->hasMoreElements())
+                ret.emplace_back(xPart);
+        }
+        return ret;
+    }
+    catch (const uno::RuntimeException&)
+    {
+        throw;
+    }
+    catch (const uno::Exception& e)
+    {
+        throw lang::WrappedTargetRuntimeException("getAllParts: exception", nullptr,
+                                                  uno::makeAny(e));
+    }
+}
 
 static ucb::InteractiveAugmentedIOException
 mkException( OUString const & i_rMessage,
@@ -850,26 +892,17 @@ DocumentMetadataAccess::getElementByURI(
     return getElementByMetadataReference( beans::StringPair(path, idref) );
 }
 
-
-uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
-DocumentMetadataAccess::getMetadataGraphsWithType(
-    const uno::Reference<rdf::XURI> & i_xType)
+uno::Sequence<uno::Reference<rdf::XURI>> SAL_CALL
+DocumentMetadataAccess::getMetadataGraphsWithType(const uno::Reference<rdf::XURI>& i_xType)
 {
-    if (!i_xType.is()) {
-        throw lang::IllegalArgumentException(
-            "DocumentMetadataAccess::getMetadataGraphsWithType: "
-            "type is null", *this, 0);
+    if (!i_xType.is())
+    {
+        throw lang::IllegalArgumentException("DocumentMetadataAccess::getMetadataGraphsWithType: "
+                                             "type is null",
+                                             *this, 0);
     }
 
-    ::std::vector< uno::Reference< rdf::XURI > > ret;
-    const ::std::vector< uno::Reference< rdf::XURI > > parts(
-        getAllParts(*m_pImpl) );
-    ::std::remove_copy_if(parts.begin(), parts.end(),
-        ::std::back_inserter(ret),
-        [this, &i_xType](uno::Reference< rdf::XURI > aPart) {
-            return !isPartOfType(*m_pImpl, aPart, i_xType);
-        } );
-    return ::comphelper::containerToSequence(ret);
+    return ::comphelper::containerToSequence(getAllParts(*m_pImpl, i_xType));
 }
 
 uno::Reference<rdf::XURI> SAL_CALL
commit 15701ab315a9d4cfc9ab0b05eae11a61b008eddc
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Fri Sep 28 06:27:09 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 25 21:40:56 2019 +0200

    sw: paragraph-sign: erase metafields from copied text correctly
    
    This is relevant for paragraph signatures where the
    metadata is not yet copied and so we exclude it.
    The issue was that in some cases we didn't use
    the proper range of text and an assertion was
    triggered in debug builds.
    
    Otherwise there should be no change of behavior
    in release builds with this patch.
    
    Change-Id: I90bc2ca56d586b96d39f34c68de53d3dac6099d7
    Reviewed-on: https://gerrit.libreoffice.org/63000
    Tested-by: Jenkins
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 03fbb0c39da6..c603ebdd40d4 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -1689,7 +1689,7 @@ void SwTextNode::CopyText( SwTextNode *const pDest,
 {
     CHECK_SWPHINTS_IF_FRM(this);
     CHECK_SWPHINTS(pDest);
-    sal_Int32 nTextStartIdx = rStart.GetIndex();
+    const sal_Int32 nTextStartIdx = rStart.GetIndex();
     sal_Int32 nDestStart = rDestStart.GetIndex();      // remember old Pos
 
     if (pDest->GetDoc()->IsClipBoard() && GetNum())
@@ -1780,7 +1780,6 @@ void SwTextNode::CopyText( SwTextNode *const pDest,
 
     // Fetch end only now, because copying into self updates the start index
     // and all attributes
-    nTextStartIdx = rStart.GetIndex();
     const sal_Int32 nEnd = nTextStartIdx + nLen;
 
     // 2. copy attributes
@@ -1928,8 +1927,10 @@ void SwTextNode::CopyText( SwTextNode *const pDest,
         std::reverse(metaFieldRanges.begin(), metaFieldRanges.end());
         for (const auto& pair : metaFieldRanges)
         {
-            const SwIndex aIdx(pDest, pair.first);
-            pDest->EraseText(aIdx, pair.second - pair.first);
+            const SwIndex aIdx(pDest, std::max<sal_Int32>(pair.first - nTextStartIdx, 0));
+            const sal_Int32 nCount = pair.second - pair.first;
+            if (nCount > 0)
+                pDest->EraseText(aIdx, nCount);
         }
     }
 


More information about the Libreoffice-commits mailing list