[Libreoffice-commits] core.git: sw/CppunitTest_sw_ooxmlimport.mk sw/qa writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Dec 2 01:55:48 PST 2015


 sw/CppunitTest_sw_ooxmlimport.mk                  |    1 
 sw/qa/extras/ooxmlimport/data/tscp.docx           |binary
 sw/qa/extras/ooxmlimport/ooxmlimport.cxx          |   40 ++++++++++++++
 writerfilter/source/dmapper/DomainMapper.cxx      |    2 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |    2 
 writerfilter/source/dmapper/SmartTagHandler.cxx   |   62 +++++++++++++++++++++-
 writerfilter/source/dmapper/SmartTagHandler.hxx   |   15 ++++-
 7 files changed, 118 insertions(+), 4 deletions(-)

New commits:
commit 831492f3d50f3d131f458f4ec0e5e802b612923f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Dec 2 10:38:20 2015 +0100

    DOCX import: handle <w:smartTag>
    
    These can be sort of arbitrary key-value pairs around one or multiple
    runs, handle the following subset:
    
    - when they appear at a paragraph context -> we assume they are
      annotations on the paragraph
    - when the smart tag's URI/element is RDF -> we map these to RDF
      metadata statements on paragraphs
    - when the attribute name's namespace is known, because in ODF we need
      to specify both a path and a type (namespace) for the RDF graph, and
      OOXML only provides a namespace
    
    As a start, recognize the TSCP BAF namespace from
    <https://www.tscp.org/wp-content/uploads/2013/08/TSCP_BAFv1.pdf>.
    
    Change-Id: Ib188b1395e7ec7e0441b4f12f86cfef99fb9f096

diff --git a/sw/CppunitTest_sw_ooxmlimport.mk b/sw/CppunitTest_sw_ooxmlimport.mk
index 5aae15d..4074255 100644
--- a/sw/CppunitTest_sw_ooxmlimport.mk
+++ b/sw/CppunitTest_sw_ooxmlimport.mk
@@ -95,6 +95,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_ooxmlimport,\
     ucb/source/ucp/file/ucpfile1 \
     unotools/util/utl \
     unoxml/source/service/unoxml \
+    unoxml/source/rdf/unordf \
     writerfilter/util/writerfilter \
     xmloff/util/xo \
 ))
diff --git a/sw/qa/extras/ooxmlimport/data/tscp.docx b/sw/qa/extras/ooxmlimport/data/tscp.docx
new file mode 100644
index 0000000..3cda72d
Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/tscp.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index e19d1ba..a4bb78b 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -79,6 +79,8 @@
 #include <unotools/streamwrap.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/rdf/URI.hpp>
+#include <com/sun/star/rdf/Statement.hpp>
 
 #include <bordertest.hxx>
 
@@ -2841,6 +2843,44 @@ DECLARE_OOXMLIMPORT_TEST(testIndents, "indents.docx")
     } while (xParaEnum->hasMoreElements());
 }
 
+DECLARE_OOXMLIMPORT_TEST(testTscp, "tscp.docx")
+{
+    uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, "urn:tscp:names:baf:1.1");
+    uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(mxComponent, uno::UNO_QUERY);
+    uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+    // This failed, no graphs had the urn:tscp:names:baf:1.1 type.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aGraphNames.getLength());
+    uno::Reference<rdf::XURI> xGraphName = aGraphNames[0];
+    uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName);
+
+    // No RDF statement on the first paragraph.
+    uno::Reference<rdf::XResource> xParagraph(getParagraph(1), uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(xParagraph, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
+    CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(xStatements->hasMoreElements()));
+
+    // 3 RDF statements on the second paragraph.
+    xParagraph.set(getParagraph(2), uno::UNO_QUERY);
+    std::map<OUString, OUString> aExpectedStatements = {
+        {"urn:tscp:names:baf:1.1#BusinessAuthorization", "urn:example:tscp:1"},
+        {"urn:tscp:names:baf:1.1#BusinessAuthorizationCategory", "urn:example:tscp:1:confidential"},
+        {"urn:tscp:names:baf:1.1#BusinessAuthorizationDate", "2015-11-27T11:45:00"}
+    };
+    std::map<OUString, OUString> aActualStatements;
+    xStatements = xGraph->getStatements(xParagraph, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
+    while (xStatements->hasMoreElements())
+    {
+        rdf::Statement aStatement = xStatements->nextElement().get<rdf::Statement>();
+        aActualStatements[aStatement.Predicate->getNamespace() + aStatement.Predicate->getLocalName()] = aStatement.Object->getStringValue();
+    }
+    CPPUNIT_ASSERT(aExpectedStatements == aActualStatements);
+
+    // No RDF statement on the third paragraph.
+    xParagraph.set(getParagraph(3), uno::UNO_QUERY);
+    xStatements = xGraph->getStatements(xParagraph, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>());
+    CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(xStatements->hasMoreElements()));
+}
+
 DECLARE_OOXMLIMPORT_TEST(testTdf92454, "tdf92454.docx")
 {
     // The first paragraph had a large indentation / left margin as inheritance
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 572f444..fb48b9a 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2662,7 +2662,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext )
     case NS_ooxml::LN_CT_SmartTagRun_smartTagPr:
     {
         writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
-        if (pProperties.get())
+        if (pProperties.get() && m_pImpl->GetTopContextType() == CONTEXT_PARAGRAPH)
             pProperties->resolve(m_pImpl->getSmartTagHandler());
     }
     break;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index ef126b8..2d858d4 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -226,6 +226,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_xAnnotationField(),
         m_nAnnotationId( -1 ),
         m_aAnnotationPositions(),
+        m_aSmartTagHandler(m_xComponentContext, m_xTextDocument),
         m_xInsertTextRange(rMediaDesc.getUnpackedValueOrDefault("TextInsertModeRange", uno::Reference<text::XTextRange>())),
         m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
         m_bInTableStyleRunProps(false),
@@ -1154,6 +1155,7 @@ void DomainMapper_Impl::finishParagraph( PropertyMapPtr pPropertyMap )
                     }
                 }
                 getTableManager( ).handle(xTextRange);
+                m_aSmartTagHandler.handle(xTextRange);
 
                 // Get the end of paragraph character inserted
                 uno::Reference< text::XTextCursor > xCur = xTextRange->getText( )->createTextCursor( );
diff --git a/writerfilter/source/dmapper/SmartTagHandler.cxx b/writerfilter/source/dmapper/SmartTagHandler.cxx
index 7c44cde..dc9f094 100644
--- a/writerfilter/source/dmapper/SmartTagHandler.cxx
+++ b/writerfilter/source/dmapper/SmartTagHandler.cxx
@@ -8,8 +8,22 @@
  */
 
 #include <SmartTagHandler.hxx>
+
+#include <com/sun/star/rdf/URI.hpp>
+
 #include <ooxml/resourceids.hxx>
 
+namespace
+{
+OUString lcl_getTypePath(const OUString& rType)
+{
+    OUString aRet;
+    if (rType == "urn:tscp:names:baf:1.1")
+        aRet = "tscp/baf.rdf";
+    return aRet;
+}
+}
+
 namespace writerfilter
 {
 namespace dmapper
@@ -17,8 +31,10 @@ namespace dmapper
 
 using namespace ::com::sun::star;
 
-SmartTagHandler::SmartTagHandler()
-    : LoggedProperties("SmartTagHandler")
+SmartTagHandler::SmartTagHandler(const uno::Reference<uno::XComponentContext>& xComponentContext, const uno::Reference<text::XTextDocument>& xTextDocument)
+    : LoggedProperties("SmartTagHandler"),
+      m_xComponentContext(xComponentContext),
+      m_xDocumentMetadataAccess(xTextDocument, uno::UNO_QUERY)
 {
 }
 
@@ -31,8 +47,11 @@ void SmartTagHandler::lcl_attribute(Id nName, Value& rValue)
     switch (nName)
     {
     case NS_ooxml::LN_CT_Attr_name:
+        m_aAttributes.emplace_back(rValue.getString(), OUString());
         break;
     case NS_ooxml::LN_CT_Attr_val:
+        if (!m_aAttributes.empty())
+            m_aAttributes.back().second = rValue.getString();
         break;
     default:
         SAL_WARN("writerfilter", "SmartTagHandler::lcl_attribute: unhandled attribute " << nName << " (string value: '"<<rValue.getString()<<"')");
@@ -64,6 +83,45 @@ void SmartTagHandler::setElement(const OUString& rElement)
     m_aElement = rElement;
 }
 
+void SmartTagHandler::handle(const uno::Reference<text::XTextRange>& xParagraph)
+{
+    if (!m_aURI.isEmpty() && !m_aElement.isEmpty() && !m_aAttributes.empty())
+    {
+        uno::Reference<rdf::XResource> xSubject(xParagraph, uno::UNO_QUERY);
+
+        for (const std::pair<OUString, OUString>& rAttribute : m_aAttributes)
+        {
+            sal_Int32 nIndex = rAttribute.first.indexOf('#');
+            if (nIndex == -1)
+                continue;
+
+            OUString aTypeNS = rAttribute.first.copy(0, nIndex);
+            OUString aMetadataFilePath = lcl_getTypePath(aTypeNS);
+            if (aMetadataFilePath.isEmpty())
+                continue;
+
+            uno::Reference<rdf::XURI> xType = rdf::URI::create(m_xComponentContext, aTypeNS);
+            uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = m_xDocumentMetadataAccess->getMetadataGraphsWithType(xType);
+            uno::Reference<rdf::XURI> xGraphName;
+            if (aGraphNames.hasElements())
+                xGraphName = aGraphNames[0];
+            else
+            {
+                uno::Sequence< uno::Reference<rdf::XURI> > xTypes = { xType };
+                xGraphName = m_xDocumentMetadataAccess->addMetadataFile(aMetadataFilePath, xTypes);
+            }
+            uno::Reference<rdf::XNamedGraph> xGraph = m_xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName);
+            uno::Reference<rdf::XURI> xKey = rdf::URI::create(m_xComponentContext, rAttribute.first);
+            uno::Reference<rdf::XURI> xValue = rdf::URI::create(m_xComponentContext, rAttribute.second);
+            xGraph->addStatement(xSubject, xKey, xValue);
+        }
+
+        m_aURI.clear();
+        m_aElement.clear();
+        m_aAttributes.clear();
+    }
+}
+
 } // namespace dmapper
 } // namespace writerfilter
 
diff --git a/writerfilter/source/dmapper/SmartTagHandler.hxx b/writerfilter/source/dmapper/SmartTagHandler.hxx
index ae5996b..e6a4a23 100644
--- a/writerfilter/source/dmapper/SmartTagHandler.hxx
+++ b/writerfilter/source/dmapper/SmartTagHandler.hxx
@@ -9,6 +9,13 @@
 #ifndef INCLUDED_WRITERFILTER_SOURCE_DMAPPER_SMARTTAGHANDLER_HXX
 #define INCLUDED_WRITERFILTER_SOURCE_DMAPPER_SMARTTAGHANDLER_HXX
 
+#include <vector>
+
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
 #include "LoggedResources.hxx"
 
 namespace writerfilter
@@ -20,11 +27,14 @@ namespace dmapper
 class SmartTagHandler
     : public LoggedProperties
 {
+    css::uno::Reference<css::uno::XComponentContext> m_xComponentContext;
+    css::uno::Reference<css::rdf::XDocumentMetadataAccess> m_xDocumentMetadataAccess;
     OUString m_aURI;
     OUString m_aElement;
+    std::vector< std::pair<OUString, OUString> > m_aAttributes;
 
 public:
-    SmartTagHandler();
+    SmartTagHandler(const css::uno::Reference<css::uno::XComponentContext>& xComponentContext, const css::uno::Reference<css::text::XTextDocument>& xTextDocument);
     virtual ~SmartTagHandler();
 
     virtual void lcl_attribute(Id Name, Value& val) override;
@@ -32,6 +42,9 @@ public:
 
     void setURI(const OUString& rURI);
     void setElement(const OUString& rElement);
+
+    /// Set m_aAttributes as RDF statements on xParagraph.
+    void handle(const css::uno::Reference<css::text::XTextRange>& xParagraph);
 };
 
 } // namespace dmapper


More information about the Libreoffice-commits mailing list