[Libreoffice-commits] core.git: sw/inc sw/source

Ashod Nakashian ashodnakashian at yahoo.com
Tue Nov 7 04:11:25 UTC 2017


 sw/inc/editsh.hxx              |    3 
 sw/source/core/edit/edfcol.cxx |  170 ++++++++++++++++++++++++++++++++++++-----
 sw/source/core/edit/edws.cxx   |    3 
 3 files changed, 158 insertions(+), 18 deletions(-)

New commits:
commit 240bf89a5221664414cfab7ff4d7d1dd35662f1e
Author: Ashod Nakashian <ashodnakashian at yahoo.com>
Date:   Fri Nov 3 07:25:01 2017 -0400

    TSCP: Restore paragraph signature when importing DOC(X)
    
    And wrap getStatements in try/catch, as it can
    throw in some cases with nasty consequences.
    
    Change-Id: I19b0d41188e8835ca4308bcef2f05907e98faf3d
    Reviewed-on: https://gerrit.libreoffice.org/44258
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 4461d9b0a04a..c076ac7e8ba1 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -383,6 +383,9 @@ public:
     /// Validate all paragraph signatures.
     void ValidateAllParagraphSignatures(bool updateDontRemove);
 
+    /// Restore the metadata fields, if missing, from the RDF metadata.
+    void RestoreMetadataFields();
+
     /// Ensure that the classification of the doc is never lower than
     /// the paragraph with the highest classification.
     void ClassifyDocPerHighestParagraphClass();
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 076982dae2e1..f1b2d7c7ec61 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -246,14 +246,28 @@ OString lcl_getParagraphBodyText(const uno::Reference<text::XTextContent>& xText
     return strBuf.makeStringAndClear().trim().toUtf8();
 }
 
+template <typename T>
+std::map<OUString, OUString> lcl_getRDFStatements(const uno::Reference<frame::XModel>& xModel,
+                                                  const T& xRef)
+{
+    try
+    {
+        const css::uno::Reference<css::rdf::XResource> xSubject(xRef, uno::UNO_QUERY);
+        return SwRDFHelper::getStatements(xModel, MetaNS, xSubject);
+    }
+    catch (const ::css::uno::Exception&)
+    {
+    }
+
+    return std::map<OUString, OUString>();
+}
+
 /// Returns RDF (key, value) pair associated with the field, if any.
 std::pair<OUString, OUString> lcl_getFieldRDFByPrefix(const uno::Reference<frame::XModel>& xModel,
                                                       const uno::Reference<css::text::XTextField>& xField,
                                                       const OUString& sPrefix)
 {
-    const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY);
-    std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject);
-    for (const auto& pair : aStatements)
+    for (const auto& pair : lcl_getRDFStatements(xModel, xField))
     {
         if (pair.first.startsWith(sPrefix))
             return pair;
@@ -267,10 +281,9 @@ std::pair<OUString, OUString> lcl_getFieldRDF(const uno::Reference<frame::XModel
                                               const uno::Reference<css::text::XTextField>& xField,
                                               const OUString& sRDFName)
 {
-    const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY);
-    std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject);
+    const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xField);
     const auto it = aStatements.find(sRDFName);
-    return it != aStatements.end() ? std::make_pair(it->first, it->second) : std::make_pair(OUString(), OUString());
+    return (it != aStatements.end()) ? std::make_pair(it->first, it->second) : std::make_pair(OUString(), OUString());
 }
 
 /// Returns true iff the field in question is paragraph signature.
@@ -281,6 +294,41 @@ bool lcl_IsParagraphSignatureField(const uno::Reference<frame::XModel>& xModel,
     return (lcl_getFieldRDF(xModel, xField, ParagraphSignatureIdRDFName).first == ParagraphSignatureIdRDFName);
 }
 
+uno::Reference<text::XTextField> lcl_findFieldByRDF(const uno::Reference<frame::XModel>& xModel,
+                                                    const uno::Reference<text::XTextContent>& xParagraph,
+                                                    const OUString& sRDFName,
+                                                    const OUString& sRDFValue = OUString())
+{
+    uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraph, uno::UNO_QUERY);
+    if (!xTextPortionEnumerationAccess.is())
+        return uno::Reference<text::XTextField>();
+
+    uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration();
+    if (!xTextPortions.is())
+        return uno::Reference<text::XTextField>();
+
+    while (xTextPortions->hasMoreElements())
+    {
+        uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
+        OUString aTextPortionType;
+        xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType;
+        if (aTextPortionType != UNO_NAME_TEXT_FIELD)
+            continue;
+
+        uno::Reference<lang::XServiceInfo> xTextField;
+        xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xTextField;
+        if (!xTextField->supportsService(MetadataFieldServiceName))
+            continue;
+
+        uno::Reference<text::XTextField> xField(xTextField, uno::UNO_QUERY);
+        std::pair<OUString, OUString> pair = lcl_getFieldRDF(xModel, xField, sRDFName);
+        if (pair.first == sRDFName && (sRDFValue.isEmpty() || sRDFValue == pair.second))
+            return xField;
+    }
+
+    return uno::Reference<text::XTextField>();
+}
+
 struct SignatureDescr
 {
     OUString msSignature;
@@ -298,8 +346,7 @@ SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel
     SignatureDescr aDescr;
     aDescr.msId = sFieldId;
 
-    const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY);
-    const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject);
+    const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xParagraph);
     const auto itSig = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureDigestRDFName);
     aDescr.msSignature = (itSig != aStatements.end() ? itSig->second : OUString());
 
@@ -316,8 +363,7 @@ SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel
                                      const uno::Reference<css::text::XTextContent>& xParagraph,
                                      const uno::Reference<css::text::XTextField>& xField)
 {
-    const css::uno::Reference<css::rdf::XResource> xFieldSubject(xField, uno::UNO_QUERY);
-    std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xFieldSubject);
+    const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xField);
     const auto itId = aStatements.find(ParagraphSignatureIdRDFName);
     return (itId != aStatements.end() ? lcl_getSignatureDescr(xModel, xParagraph, itId->second) : SignatureDescr());
 }
@@ -369,8 +415,7 @@ lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel,
 OUString lcl_getNextSignatureId(const uno::Reference<frame::XModel>& xModel,
                                 const uno::Reference<text::XTextContent>& xParagraph)
 {
-    const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY);
-    std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject);
+    const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xParagraph);
     const auto it = aStatements.find(ParagraphSignatureLastIdRDFName);
     return OUString::number(it != aStatements.end() ? it->second.toInt32() + 1 : 1);
 }
@@ -556,8 +601,7 @@ void lcl_ValidateParagraphSignatures(SwDoc* pDoc, const uno::Reference<text::XTe
     // Check if the paragraph is signed.
     try
     {
-        const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY);
-        const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject);
+        const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xParagraph);
         if (aStatements.find(ParagraphSignatureLastIdRDFName) == aStatements.end())
             return;
     }
@@ -1525,9 +1569,7 @@ SwUndoParagraphSigning::SwUndoParagraphSigning(SwDoc* pDoc,
 {
     // Save the metadata and field content to undo/redo.
     uno::Reference<frame::XModel> xModel = m_pDoc->GetDocShell()->GetBaseModel();
-    const css::uno::Reference<css::rdf::XResource> xSubject(m_xField, uno::UNO_QUERY);
-
-    std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject);
+    const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, m_xField);
     const auto it = aStatements.find(ParagraphSignatureIdRDFName);
     if (it != aStatements.end())
         m_signature = it->second;
@@ -1728,7 +1770,7 @@ uno::Reference<text::XTextField> lcl_GetParagraphMetadataFieldAtIndex(const SwDo
             {
                 const css::uno::Reference<css::rdf::XResource> xSubject(pMeta->MakeUnoObject(), uno::UNO_QUERY);
                 uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel();
-                const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject);
+                const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xSubject);
                 if (aStatements.find(ParagraphSignatureIdRDFName) != aStatements.end() ||
                     aStatements.find(ParagraphClassificationNameRDFName) != aStatements.end())
                 {
@@ -1741,6 +1783,98 @@ uno::Reference<text::XTextField> lcl_GetParagraphMetadataFieldAtIndex(const SwDo
     return xTextField;
 }
 
+void SwEditShell::RestoreMetadataFields()
+{
+    SwDocShell* pDocShell = GetDoc()->GetDocShell();
+    if (!pDocShell || !IsParagraphSignatureValidationEnabled())
+        return;
+
+    // Prevent recursive validation since this is triggered on node updates, which we do below.
+    const bool bOldValidationFlag = SetParagraphSignatureValidation(false);
+    comphelper::ScopeGuard const g([this, bOldValidationFlag] () {
+            SetParagraphSignatureValidation(bOldValidationFlag);
+        });
+
+    uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
+    const uno::Reference<text::XTextDocument> xDoc(xModel, uno::UNO_QUERY);
+    uno::Reference<text::XText> xParent = xDoc->getText();
+    uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xParent, uno::UNO_QUERY);
+    if (!xParagraphEnumerationAccess.is())
+        return;
+    uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration();
+    if (!xParagraphs.is())
+        return;
+    while (xParagraphs->hasMoreElements())
+    {
+        uno::Reference<text::XTextContent> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY);
+
+        std::map<OUString, SignatureDescr> aSignatures;
+
+        std::vector<svx::ClassificationResult> aResult;
+
+        const sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
+
+        const OUString sBlank("");
+        for (const auto& pair : lcl_getRDFStatements(xModel, xParagraph))
+        {
+            const OUString aName = pair.first;
+            const OUString aValue = pair.second;
+
+            if (aKeyCreator.isMarkingTextKey(aName))
+            {
+                aResult.push_back({ svx::ClassificationType::TEXT, aValue, sBlank, sBlank });
+            }
+            else if (aKeyCreator.isCategoryNameKey(aName) || aKeyCreator.isCategoryIdentifierKey(aName))
+            {
+                aResult.push_back({ svx::ClassificationType::CATEGORY, aValue, sBlank, sBlank });
+            }
+            else if (aKeyCreator.isMarkingKey(aName))
+            {
+                aResult.push_back({ svx::ClassificationType::MARKING, aValue, sBlank, sBlank });
+            }
+            else if (aKeyCreator.isIntellectualPropertyPartKey(aName))
+            {
+                // aResult.push_back({ svx::ClassificationType::INTELLECTUAL_PROPERTY_PART, xTextRange->getString(), sBlank, sBlank });
+            }
+            else if (aName.startsWith(ParagraphSignatureRDFNamespace))
+            {
+                OUString sSuffix = aName.copy(ParagraphSignatureRDFNamespace.getLength());
+                sal_Int32 index = sSuffix.indexOf(":");
+                if (index >= 0)
+                {
+                    OUString id = sSuffix.copy(0, index);
+                    OUString type = sSuffix.copy(index);
+                    if (type == ParagraphSignatureDateRDFName)
+                        aSignatures[id].msDate = aValue;
+                    else if (type == ParagraphSignatureUsageRDFName)
+                        aSignatures[id].msUsage = aValue;
+                    else if (type == ParagraphSignatureDigestRDFName)
+                        aSignatures[id].msSignature = aValue;
+                }
+            }
+        }
+
+        for (const auto& pair : aSignatures)
+        {
+            uno::Reference<text::XTextField> xField = lcl_findFieldByRDF(xModel, xParagraph, ParagraphSignatureIdRDFName, pair.first);
+            if (!xField.is())
+            {
+                uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
+                xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY);
+
+                // Add the signature at the end.
+                xField->attach(xParagraph->getAnchor()->getEnd());
+
+                const css::uno::Reference<css::rdf::XResource> xFieldSubject(xField, uno::UNO_QUERY);
+                SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xFieldSubject, ParagraphSignatureIdRDFName, pair.first);
+
+                const OString utf8Text = lcl_getParagraphBodyText(xParagraph);
+                lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xParagraph, xField, utf8Text);
+            }
+        }
+    }
+}
+
 bool SwEditShell::IsCursorInParagraphMetadataField() const
 {
     SwTextNode* pNode = GetCursor()->Start()->nNode.GetNode().GetTextNode();
diff --git a/sw/source/core/edit/edws.cxx b/sw/source/core/edit/edws.cxx
index 73f8c6aba112..fc7ed9683311 100644
--- a/sw/source/core/edit/edws.cxx
+++ b/sw/source/core/edit/edws.cxx
@@ -51,6 +51,9 @@ 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);


More information about the Libreoffice-commits mailing list