163bba73cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
363bba73cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
463bba73cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
563bba73cSAndrew Rist  * distributed with this work for additional information
663bba73cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
763bba73cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
863bba73cSAndrew Rist  * "License"); you may not use this file except in compliance
963bba73cSAndrew Rist  * with the License.  You may obtain a copy of the License at
1063bba73cSAndrew Rist  *
1163bba73cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1263bba73cSAndrew Rist  *
1363bba73cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1463bba73cSAndrew Rist  * software distributed under the License is distributed on an
1563bba73cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1663bba73cSAndrew Rist  * KIND, either express or implied.  See the License for the
1763bba73cSAndrew Rist  * specific language governing permissions and limitations
1863bba73cSAndrew Rist  * under the License.
1963bba73cSAndrew Rist  *
2063bba73cSAndrew Rist  *************************************************************/
2163bba73cSAndrew Rist 
2263bba73cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "precompiled_xmloff.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "RDFaImportHelper.hxx"
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <xmloff/xmlimp.hxx>
29cdf0e10cSrcweir #include <xmloff/nmspmap.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <comphelper/sequenceasvector.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <tools/string.hxx> // for GetAbsoluteReference
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <com/sun/star/rdf/URI.hpp>
36cdf0e10cSrcweir #include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
37cdf0e10cSrcweir #include <com/sun/star/rdf/XDocumentRepository.hpp>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <rtl/ustring.hxx>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #include <boost/bind.hpp>
42cdf0e10cSrcweir #include <boost/iterator_adaptors.hpp>
43cdf0e10cSrcweir #ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ // from iterator_adaptors.hpp
44cdf0e10cSrcweir // N.B.: the check for the header guard _of a specific version of boost_
45cdf0e10cSrcweir //       is here so this may work on different versions of boost,
46cdf0e10cSrcweir //       which sadly put the goods in different header files
47cdf0e10cSrcweir #include <boost/iterator/transform_iterator.hpp>
48cdf0e10cSrcweir #endif
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include <map>
51cdf0e10cSrcweir #include <iterator>
52cdf0e10cSrcweir #include <functional>
53cdf0e10cSrcweir #include <algorithm>
54cdf0e10cSrcweir 
55cdf0e10cSrcweir 
56cdf0e10cSrcweir using namespace ::com::sun::star;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir namespace xmloff {
59cdf0e10cSrcweir 
60cdf0e10cSrcweir /** a bit of context for parsing RDFa attributes */
61cdf0e10cSrcweir class SAL_DLLPRIVATE RDFaReader
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     const SvXMLImport & m_rImport;
64cdf0e10cSrcweir 
GetImport() const65cdf0e10cSrcweir     const SvXMLImport & GetImport() const { return m_rImport; }
66cdf0e10cSrcweir 
67cdf0e10cSrcweir     //FIXME: this is an ugly hack to workaround buggy SvXMLImport::GetAbsolute
GetAbsoluteReference(::rtl::OUString const & i_rURI) const68cdf0e10cSrcweir     ::rtl::OUString GetAbsoluteReference(::rtl::OUString const & i_rURI) const
69cdf0e10cSrcweir     {
70cdf0e10cSrcweir         if (!i_rURI.getLength() || i_rURI[0] == '#')
71cdf0e10cSrcweir         {
72cdf0e10cSrcweir             return GetImport().GetBaseURL() + i_rURI;
73cdf0e10cSrcweir         }
74cdf0e10cSrcweir         else
75cdf0e10cSrcweir         {
76cdf0e10cSrcweir             return GetImport().GetAbsoluteReference(i_rURI);
77cdf0e10cSrcweir         }
78cdf0e10cSrcweir     }
79cdf0e10cSrcweir 
80cdf0e10cSrcweir public:
RDFaReader(SvXMLImport const & i_rImport)81cdf0e10cSrcweir     RDFaReader(SvXMLImport const & i_rImport)
82cdf0e10cSrcweir         : m_rImport(i_rImport)
83cdf0e10cSrcweir     { }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir     // returns URI or blank node!
86cdf0e10cSrcweir     ::rtl::OUString ReadCURIE(::rtl::OUString const & i_rCURIE) const;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     std::vector< ::rtl::OUString >
89cdf0e10cSrcweir     ReadCURIEs(::rtl::OUString const & i_rCURIEs) const;
90cdf0e10cSrcweir 
91cdf0e10cSrcweir     ::rtl::OUString
92cdf0e10cSrcweir     ReadURIOrSafeCURIE( ::rtl::OUString const & i_rURIOrSafeCURIE) const;
93cdf0e10cSrcweir };
94cdf0e10cSrcweir 
95cdf0e10cSrcweir /** helper to insert RDFa statements into the RDF repository */
96cdf0e10cSrcweir class SAL_DLLPRIVATE RDFaInserter
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     const uno::Reference<uno::XComponentContext> m_xContext;
99cdf0e10cSrcweir     uno::Reference< rdf::XDocumentRepository > m_xRepository;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir     typedef ::std::map< ::rtl::OUString, uno::Reference< rdf::XBlankNode > >
102cdf0e10cSrcweir         BlankNodeMap_t;
103cdf0e10cSrcweir 
104cdf0e10cSrcweir     BlankNodeMap_t m_BlankNodeMap;
105cdf0e10cSrcweir 
106cdf0e10cSrcweir public:
RDFaInserter(uno::Reference<uno::XComponentContext> const & i_xContext,uno::Reference<rdf::XDocumentRepository> const & i_xRepository)107cdf0e10cSrcweir     RDFaInserter(uno::Reference<uno::XComponentContext> const & i_xContext,
108cdf0e10cSrcweir             uno::Reference< rdf::XDocumentRepository > const & i_xRepository)
109cdf0e10cSrcweir         : m_xContext(i_xContext)
110cdf0e10cSrcweir         , m_xRepository(i_xRepository)
111cdf0e10cSrcweir     {}
112cdf0e10cSrcweir 
113cdf0e10cSrcweir     uno::Reference< rdf::XBlankNode >
114cdf0e10cSrcweir     LookupBlankNode(::rtl::OUString const & i_rNodeId );
115cdf0e10cSrcweir 
116cdf0e10cSrcweir     uno::Reference< rdf::XURI >
117cdf0e10cSrcweir     MakeURI( ::rtl::OUString const & i_rURI) const;
118cdf0e10cSrcweir 
119cdf0e10cSrcweir     uno::Reference< rdf::XResource>
120cdf0e10cSrcweir     MakeResource( ::rtl::OUString const & i_rResource);
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     void InsertRDFaEntry(struct RDFaEntry const & i_rEntry);
123cdf0e10cSrcweir };
124cdf0e10cSrcweir 
125cdf0e10cSrcweir /** store parsed RDFa attributes */
126cdf0e10cSrcweir struct SAL_DLLPRIVATE ParsedRDFaAttributes
127cdf0e10cSrcweir {
128cdf0e10cSrcweir     ::rtl::OUString m_About;
129cdf0e10cSrcweir     ::std::vector< ::rtl::OUString > m_Properties;
130cdf0e10cSrcweir     ::rtl::OUString m_Content;
131cdf0e10cSrcweir     ::rtl::OUString m_Datatype;
132cdf0e10cSrcweir 
ParsedRDFaAttributesxmloff::ParsedRDFaAttributes133cdf0e10cSrcweir     ParsedRDFaAttributes(
134cdf0e10cSrcweir             ::rtl::OUString const & i_rAbout,
135cdf0e10cSrcweir             ::std::vector< ::rtl::OUString > const & i_rProperties,
136cdf0e10cSrcweir             ::rtl::OUString const & i_rContent,
137cdf0e10cSrcweir             ::rtl::OUString const & i_rDatatype)
138cdf0e10cSrcweir         : m_About(i_rAbout)
139cdf0e10cSrcweir         , m_Properties(i_rProperties)
140cdf0e10cSrcweir         , m_Content(i_rContent)
141cdf0e10cSrcweir         , m_Datatype(i_rDatatype)
142cdf0e10cSrcweir     { }
143cdf0e10cSrcweir };
144cdf0e10cSrcweir 
145cdf0e10cSrcweir /** store metadatable object and its RDFa attributes */
146cdf0e10cSrcweir struct SAL_DLLPRIVATE RDFaEntry
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     uno::Reference<rdf::XMetadatable> m_xObject;
149cdf0e10cSrcweir     ::boost::shared_ptr<ParsedRDFaAttributes> m_pRDFaAttributes;
150cdf0e10cSrcweir 
RDFaEntryxmloff::RDFaEntry151cdf0e10cSrcweir     RDFaEntry(uno::Reference<rdf::XMetadatable> const & i_xObject,
152cdf0e10cSrcweir             ::boost::shared_ptr<ParsedRDFaAttributes> const& i_pRDFaAttributes)
153cdf0e10cSrcweir         : m_xObject(i_xObject)
154cdf0e10cSrcweir         , m_pRDFaAttributes(i_pRDFaAttributes)
155cdf0e10cSrcweir     { }
156cdf0e10cSrcweir };
157cdf0e10cSrcweir 
158cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 
isWS(const sal_Unicode i_Char)161cdf0e10cSrcweir static inline bool isWS(const sal_Unicode i_Char)
162cdf0e10cSrcweir {
163cdf0e10cSrcweir     return ('\t' == i_Char) || ('\n' == i_Char) || ('\r' == i_Char)
164cdf0e10cSrcweir         || (' ' == i_Char);
165cdf0e10cSrcweir }
166cdf0e10cSrcweir 
splitAtWS(::rtl::OUString & io_rString)167cdf0e10cSrcweir static ::rtl::OUString splitAtWS(::rtl::OUString & io_rString)
168cdf0e10cSrcweir {
169cdf0e10cSrcweir     const sal_Int32 len( io_rString.getLength() );
170cdf0e10cSrcweir     sal_Int32 idxstt(0);
171cdf0e10cSrcweir     while ((idxstt < len) && ( isWS(io_rString[idxstt])))
172cdf0e10cSrcweir         ++idxstt; // skip leading ws
173cdf0e10cSrcweir     sal_Int32 idxend(idxstt);
174cdf0e10cSrcweir     while ((idxend < len) && (!isWS(io_rString[idxend])))
175cdf0e10cSrcweir         ++idxend; // the CURIE
176cdf0e10cSrcweir     const ::rtl::OUString ret(io_rString.copy(idxstt, idxend - idxstt));
177cdf0e10cSrcweir     io_rString = io_rString.copy(idxend); // rest
178cdf0e10cSrcweir     return ret;
179cdf0e10cSrcweir }
180cdf0e10cSrcweir 
181cdf0e10cSrcweir ::rtl::OUString
ReadCURIE(::rtl::OUString const & i_rCURIE) const182cdf0e10cSrcweir RDFaReader::ReadCURIE(::rtl::OUString const & i_rCURIE) const
183cdf0e10cSrcweir {
184cdf0e10cSrcweir     // the RDFa spec says that a prefix is required (it may be empty: ":foo")
185cdf0e10cSrcweir     const sal_Int32 idx( i_rCURIE.indexOf(':') );
186cdf0e10cSrcweir     if (idx >= 0)
187cdf0e10cSrcweir     {
188cdf0e10cSrcweir         ::rtl::OUString Prefix;
189cdf0e10cSrcweir         ::rtl::OUString LocalName;
190cdf0e10cSrcweir         ::rtl::OUString Namespace;
191cdf0e10cSrcweir         sal_uInt16 nKey( GetImport().GetNamespaceMap()._GetKeyByAttrName(
192cdf0e10cSrcweir             i_rCURIE, &Prefix, &LocalName, &Namespace) );
193cdf0e10cSrcweir         if (Prefix.equalsAscii("_"))
194cdf0e10cSrcweir         {
195cdf0e10cSrcweir             // eeek, it's a bnode!
196cdf0e10cSrcweir             // "_" is not a valid URI scheme => we can identify bnodes
197cdf0e10cSrcweir             return i_rCURIE;
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir         else
200cdf0e10cSrcweir         {
201cdf0e10cSrcweir             OSL_ENSURE(XML_NAMESPACE_NONE != nKey, "no namespace?");
202cdf0e10cSrcweir             if ((XML_NAMESPACE_UNKNOWN != nKey) &&
203cdf0e10cSrcweir                 (XML_NAMESPACE_XMLNS   != nKey))
204cdf0e10cSrcweir             {
205cdf0e10cSrcweir                 // N.B.: empty LocalName is valid!
206cdf0e10cSrcweir                 const ::rtl::OUString URI(Namespace + LocalName);
207cdf0e10cSrcweir //                return GetImport().GetAbsoluteReference(URI);
208cdf0e10cSrcweir                 return GetAbsoluteReference(URI);
209cdf0e10cSrcweir             }
210cdf0e10cSrcweir             else
211cdf0e10cSrcweir             {
212cdf0e10cSrcweir                 OSL_TRACE( "ReadCURIE: invalid CURIE: invalid prefix" );
213cdf0e10cSrcweir             }
214cdf0e10cSrcweir         }
215cdf0e10cSrcweir     }
216cdf0e10cSrcweir     else
217cdf0e10cSrcweir     {
218cdf0e10cSrcweir         OSL_TRACE( "ReadCURIE: invalid CURIE: no prefix" );
219cdf0e10cSrcweir     }
220*5086b727SPavel Janík 
221*5086b727SPavel Janík     return ::rtl::OUString();
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir ::std::vector< ::rtl::OUString >
ReadCURIEs(::rtl::OUString const & i_rCURIEs) const225cdf0e10cSrcweir RDFaReader::ReadCURIEs(::rtl::OUString const & i_rCURIEs) const
226cdf0e10cSrcweir {
227cdf0e10cSrcweir     std::vector< ::rtl::OUString > vec;
228cdf0e10cSrcweir     ::rtl::OUString CURIEs(i_rCURIEs);
229cdf0e10cSrcweir     do {
230cdf0e10cSrcweir       ::rtl::OUString curie( splitAtWS(CURIEs) );
231cdf0e10cSrcweir       if (curie.getLength())
232cdf0e10cSrcweir       {
233cdf0e10cSrcweir           const ::rtl::OUString uri(ReadCURIE(curie));
234cdf0e10cSrcweir           if (uri.getLength())
235cdf0e10cSrcweir           {
236cdf0e10cSrcweir               vec.push_back(uri);
237cdf0e10cSrcweir           }
238cdf0e10cSrcweir       }
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir     while (CURIEs.getLength());
241cdf0e10cSrcweir     if (!vec.size())
242cdf0e10cSrcweir     {
243cdf0e10cSrcweir         OSL_TRACE( "ReadCURIEs: invalid CURIEs" );
244cdf0e10cSrcweir     }
245cdf0e10cSrcweir     return vec;
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
248cdf0e10cSrcweir ::rtl::OUString
ReadURIOrSafeCURIE(::rtl::OUString const & i_rURIOrSafeCURIE) const249cdf0e10cSrcweir RDFaReader::ReadURIOrSafeCURIE(::rtl::OUString const & i_rURIOrSafeCURIE) const
250cdf0e10cSrcweir {
251cdf0e10cSrcweir     const sal_Int32 len(i_rURIOrSafeCURIE.getLength());
252cdf0e10cSrcweir     if (len && (i_rURIOrSafeCURIE[0] == '['))
253cdf0e10cSrcweir     {
254cdf0e10cSrcweir         if ((len >= 2) && (i_rURIOrSafeCURIE[len - 1] == ']'))
255cdf0e10cSrcweir         {
256cdf0e10cSrcweir             return ReadCURIE(i_rURIOrSafeCURIE.copy(1, len - 2));
257cdf0e10cSrcweir         }
258cdf0e10cSrcweir         else
259cdf0e10cSrcweir         {
260cdf0e10cSrcweir             OSL_TRACE( "ReadURIOrSafeCURIE: invalid SafeCURIE" );
261cdf0e10cSrcweir             return ::rtl::OUString();
262cdf0e10cSrcweir         }
263cdf0e10cSrcweir     }
264cdf0e10cSrcweir     else
265cdf0e10cSrcweir     {
266cdf0e10cSrcweir         if (i_rURIOrSafeCURIE.matchAsciiL("_:", 2)) // blank node
267cdf0e10cSrcweir         {
268cdf0e10cSrcweir             OSL_TRACE( "ReadURIOrSafeCURIE: invalid URI: scheme is _" );
269cdf0e10cSrcweir             return ::rtl::OUString();
270cdf0e10cSrcweir         }
271cdf0e10cSrcweir         else
272cdf0e10cSrcweir         {
273cdf0e10cSrcweir //            return GetImport().GetAbsoluteReference(i_rURIOrSafeCURIE);
274cdf0e10cSrcweir             return GetAbsoluteReference(i_rURIOrSafeCURIE);
275cdf0e10cSrcweir         }
276cdf0e10cSrcweir     }
277cdf0e10cSrcweir }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
280cdf0e10cSrcweir 
281cdf0e10cSrcweir uno::Reference< rdf::XBlankNode >
LookupBlankNode(::rtl::OUString const & i_rNodeId)282cdf0e10cSrcweir RDFaInserter::LookupBlankNode(::rtl::OUString const & i_rNodeId )
283cdf0e10cSrcweir {
284cdf0e10cSrcweir     uno::Reference< rdf::XBlankNode > & rEntry( m_BlankNodeMap[ i_rNodeId ] );
285cdf0e10cSrcweir     if (!rEntry.is())
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         rEntry = m_xRepository->createBlankNode();
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir     return rEntry;
290cdf0e10cSrcweir }
291cdf0e10cSrcweir 
292cdf0e10cSrcweir uno::Reference< rdf::XURI >
MakeURI(::rtl::OUString const & i_rURI) const293cdf0e10cSrcweir RDFaInserter::MakeURI( ::rtl::OUString const & i_rURI) const
294cdf0e10cSrcweir {
295cdf0e10cSrcweir     if (i_rURI.matchAsciiL("_:", 2)) // blank node
296cdf0e10cSrcweir     {
297cdf0e10cSrcweir         OSL_TRACE("MakeURI: cannot create URI for blank node");
298cdf0e10cSrcweir         return 0;
299cdf0e10cSrcweir     }
300cdf0e10cSrcweir     else
301cdf0e10cSrcweir     {
302cdf0e10cSrcweir         try
303cdf0e10cSrcweir         {
304cdf0e10cSrcweir             return rdf::URI::create( m_xContext, i_rURI );
305cdf0e10cSrcweir         }
306cdf0e10cSrcweir         catch (uno::Exception &)
307cdf0e10cSrcweir         {
308cdf0e10cSrcweir             OSL_ENSURE(false, "MakeURI: cannot create URI");
309cdf0e10cSrcweir             return 0;
310cdf0e10cSrcweir         }
311cdf0e10cSrcweir     }
312cdf0e10cSrcweir }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir uno::Reference< rdf::XResource>
MakeResource(::rtl::OUString const & i_rResource)315cdf0e10cSrcweir RDFaInserter::MakeResource( ::rtl::OUString const & i_rResource)
316cdf0e10cSrcweir {
317cdf0e10cSrcweir     if (i_rResource.matchAsciiL("_:", 2)) // blank node
318cdf0e10cSrcweir     {
319cdf0e10cSrcweir         // we cannot use the blank node label as-is: it must be distinct
320cdf0e10cSrcweir         // from labels in other graphs, so create fresh ones per XML stream
321cdf0e10cSrcweir         // N.B.: content.xml and styles.xml are distinct graphs
322cdf0e10cSrcweir         ::rtl::OUString name( i_rResource.copy(2) );
323cdf0e10cSrcweir         const uno::Reference< rdf::XBlankNode > xBNode( LookupBlankNode(name) );
324cdf0e10cSrcweir         OSL_ENSURE(xBNode.is(), "no blank node?");
325cdf0e10cSrcweir         return uno::Reference<rdf::XResource>( xBNode, uno::UNO_QUERY);
326cdf0e10cSrcweir     }
327cdf0e10cSrcweir     else
328cdf0e10cSrcweir     {
329cdf0e10cSrcweir         return uno::Reference<rdf::XResource>( MakeURI( i_rResource ),
330cdf0e10cSrcweir             uno::UNO_QUERY);
331cdf0e10cSrcweir     }
332cdf0e10cSrcweir }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir /** i wrote this because c++ implementations cannot agree on which variant
335cdf0e10cSrcweir     of boost::bind and std::mem_fun_ref applied to Reference::is compiles */
336cdf0e10cSrcweir class ref_is_null :
337cdf0e10cSrcweir     public ::std::unary_function<sal_Bool, const uno::Reference<rdf::XURI> & >
338cdf0e10cSrcweir {
339cdf0e10cSrcweir public:
operator ()(const uno::Reference<rdf::XURI> & i_rRef)340cdf0e10cSrcweir     sal_Bool operator() (const uno::Reference<rdf::XURI> & i_rRef)
341cdf0e10cSrcweir     {
342cdf0e10cSrcweir         return !i_rRef.is();
343cdf0e10cSrcweir     }
344cdf0e10cSrcweir };
345cdf0e10cSrcweir 
InsertRDFaEntry(struct RDFaEntry const & i_rEntry)346cdf0e10cSrcweir void RDFaInserter::InsertRDFaEntry(
347cdf0e10cSrcweir     struct RDFaEntry const & i_rEntry)
348cdf0e10cSrcweir {
349cdf0e10cSrcweir     OSL_ENSURE(i_rEntry.m_xObject.is(),
350cdf0e10cSrcweir         "InsertRDFaEntry: invalid arg: null object");
351cdf0e10cSrcweir     if (!i_rEntry.m_xObject.is()) return;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir     const uno::Reference< rdf::XResource > xSubject(
354cdf0e10cSrcweir         MakeResource( i_rEntry.m_pRDFaAttributes->m_About ) );
355cdf0e10cSrcweir     if (!xSubject.is())
356cdf0e10cSrcweir     {
357cdf0e10cSrcweir         return; // invalid
358cdf0e10cSrcweir     }
359cdf0e10cSrcweir 
360cdf0e10cSrcweir     ::comphelper::SequenceAsVector< uno::Reference< rdf::XURI > > predicates;
361cdf0e10cSrcweir 
362cdf0e10cSrcweir     predicates.reserve(i_rEntry.m_pRDFaAttributes->m_Properties.size());
363cdf0e10cSrcweir 
364cdf0e10cSrcweir     ::std::remove_copy_if(
365cdf0e10cSrcweir         ::boost::make_transform_iterator(
366cdf0e10cSrcweir             i_rEntry.m_pRDFaAttributes->m_Properties.begin(),
367cdf0e10cSrcweir             ::boost::bind(&RDFaInserter::MakeURI, this, _1)),
368cdf0e10cSrcweir         // argh, this must be the same type :(
369cdf0e10cSrcweir         ::boost::make_transform_iterator(
370cdf0e10cSrcweir             i_rEntry.m_pRDFaAttributes->m_Properties.end(),
371cdf0e10cSrcweir             ::boost::bind(&RDFaInserter::MakeURI, this, _1)),
372cdf0e10cSrcweir         ::std::back_inserter(predicates),
373cdf0e10cSrcweir         ref_is_null() );
374cdf0e10cSrcweir         // compiles only on wntmsci12
375cdf0e10cSrcweir //        ::boost::bind( ::std::logical_not<sal_Bool>(), ::boost::bind<sal_Bool>(&uno::Reference<rdf::XURI>::is, _1)));
376cdf0e10cSrcweir         // compiles on unxsoli4, wntsci12, but not unxlngi6
377cdf0e10cSrcweir //        ::boost::bind( ::std::logical_not<sal_Bool>(), ::boost::bind<sal_Bool, com::sun::star::uno::Reference<rdf::XURI> >(&uno::Reference<rdf::XURI>::is, _1)));
378cdf0e10cSrcweir         // compiles on unxsoli4, unxlngi6, but not wntsci12
379cdf0e10cSrcweir //        ::std::not1( ::std::mem_fun_ref(&uno::Reference<rdf::XURI>::is)) );
380cdf0e10cSrcweir 
381cdf0e10cSrcweir     if (!predicates.size())
382cdf0e10cSrcweir     {
383cdf0e10cSrcweir         return; // invalid
384cdf0e10cSrcweir     }
385cdf0e10cSrcweir 
386cdf0e10cSrcweir     uno::Reference<rdf::XURI> xDatatype;
387cdf0e10cSrcweir     if (i_rEntry.m_pRDFaAttributes->m_Datatype.getLength())
388cdf0e10cSrcweir     {
389cdf0e10cSrcweir         xDatatype = MakeURI( i_rEntry.m_pRDFaAttributes->m_Datatype );
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir 
392cdf0e10cSrcweir     try
393cdf0e10cSrcweir     {
394cdf0e10cSrcweir         // N.B.: this will call xMeta->ensureMetadataReference, which is why
395cdf0e10cSrcweir         // this must be done _after_ importing the whole XML file,
396cdf0e10cSrcweir         // to prevent collision between generated ids and ids in the file
397cdf0e10cSrcweir         m_xRepository->setStatementRDFa(xSubject, predicates.getAsConstList(),
398cdf0e10cSrcweir             i_rEntry.m_xObject,
399cdf0e10cSrcweir             i_rEntry.m_pRDFaAttributes->m_Content, xDatatype);
400cdf0e10cSrcweir     }
401cdf0e10cSrcweir     catch (uno::Exception &)
402cdf0e10cSrcweir     {
403cdf0e10cSrcweir         OSL_ENSURE(false, "InsertRDFaEntry: setStatementRDFa failed?");
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////
408cdf0e10cSrcweir 
RDFaImportHelper(const SvXMLImport & i_rImport)409cdf0e10cSrcweir RDFaImportHelper::RDFaImportHelper(const SvXMLImport & i_rImport)
410cdf0e10cSrcweir     : m_rImport(i_rImport)
411cdf0e10cSrcweir {
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
~RDFaImportHelper()414cdf0e10cSrcweir RDFaImportHelper::~RDFaImportHelper()
415cdf0e10cSrcweir {
416cdf0e10cSrcweir }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir ::boost::shared_ptr<ParsedRDFaAttributes>
ParseRDFa(::rtl::OUString const & i_rAbout,::rtl::OUString const & i_rProperty,::rtl::OUString const & i_rContent,::rtl::OUString const & i_rDatatype)419cdf0e10cSrcweir RDFaImportHelper::ParseRDFa(
420cdf0e10cSrcweir     ::rtl::OUString const & i_rAbout,
421cdf0e10cSrcweir     ::rtl::OUString const & i_rProperty,
422cdf0e10cSrcweir     ::rtl::OUString const & i_rContent,
423cdf0e10cSrcweir     ::rtl::OUString const & i_rDatatype)
424cdf0e10cSrcweir {
425cdf0e10cSrcweir     if (!i_rProperty.getLength())
426cdf0e10cSrcweir     {
427cdf0e10cSrcweir         OSL_TRACE("AddRDFa: invalid input: xhtml:property empty");
428cdf0e10cSrcweir         return ::boost::shared_ptr<ParsedRDFaAttributes>();
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir     // must parse CURIEs here: need namespace declaration context
431cdf0e10cSrcweir     RDFaReader reader(GetImport());
432cdf0e10cSrcweir     const ::rtl::OUString about( reader.ReadURIOrSafeCURIE(i_rAbout) );
433cdf0e10cSrcweir     if (!about.getLength()) {
434cdf0e10cSrcweir         return ::boost::shared_ptr<ParsedRDFaAttributes>();
435cdf0e10cSrcweir     }
436cdf0e10cSrcweir     const ::std::vector< ::rtl::OUString > properties(
437cdf0e10cSrcweir         reader.ReadCURIEs(i_rProperty) );
438cdf0e10cSrcweir     if (!properties.size()) {
439cdf0e10cSrcweir         return ::boost::shared_ptr<ParsedRDFaAttributes>();
440cdf0e10cSrcweir     }
441cdf0e10cSrcweir     const ::rtl::OUString datatype( i_rDatatype.getLength()
442cdf0e10cSrcweir         ?   reader.ReadCURIE(i_rDatatype)
443cdf0e10cSrcweir         :   ::rtl::OUString() );
444cdf0e10cSrcweir     return ::boost::shared_ptr<ParsedRDFaAttributes>(
445cdf0e10cSrcweir             new ParsedRDFaAttributes(about, properties, i_rContent, datatype));
446cdf0e10cSrcweir }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir void
AddRDFa(uno::Reference<rdf::XMetadatable> const & i_xObject,::boost::shared_ptr<ParsedRDFaAttributes> & i_pRDFaAttributes)449cdf0e10cSrcweir RDFaImportHelper::AddRDFa(
450cdf0e10cSrcweir     uno::Reference<rdf::XMetadatable> const & i_xObject,
451cdf0e10cSrcweir     ::boost::shared_ptr<ParsedRDFaAttributes> & i_pRDFaAttributes)
452cdf0e10cSrcweir {
453cdf0e10cSrcweir     if (!i_xObject.is())
454cdf0e10cSrcweir     {
455cdf0e10cSrcweir         OSL_ENSURE(false, "AddRDFa: invalid arg: null textcontent");
456cdf0e10cSrcweir         return;
457cdf0e10cSrcweir     }
458cdf0e10cSrcweir     if (!i_pRDFaAttributes.get())
459cdf0e10cSrcweir     {
460cdf0e10cSrcweir         OSL_ENSURE(false, "AddRDFa: invalid arg: null RDFa attributes");
461cdf0e10cSrcweir         return;
462cdf0e10cSrcweir     }
463cdf0e10cSrcweir     m_RDFaEntries.push_back(RDFaEntry(i_xObject, i_pRDFaAttributes));
464cdf0e10cSrcweir }
465cdf0e10cSrcweir 
466cdf0e10cSrcweir void
ParseAndAddRDFa(uno::Reference<rdf::XMetadatable> const & i_xObject,::rtl::OUString const & i_rAbout,::rtl::OUString const & i_rProperty,::rtl::OUString const & i_rContent,::rtl::OUString const & i_rDatatype)467cdf0e10cSrcweir RDFaImportHelper::ParseAndAddRDFa(
468cdf0e10cSrcweir     uno::Reference<rdf::XMetadatable> const & i_xObject,
469cdf0e10cSrcweir     ::rtl::OUString const & i_rAbout,
470cdf0e10cSrcweir     ::rtl::OUString const & i_rProperty,
471cdf0e10cSrcweir     ::rtl::OUString const & i_rContent,
472cdf0e10cSrcweir     ::rtl::OUString const & i_rDatatype)
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     ::boost::shared_ptr<ParsedRDFaAttributes> pAttributes(
475cdf0e10cSrcweir         ParseRDFa(i_rAbout, i_rProperty, i_rContent, i_rDatatype) );
476cdf0e10cSrcweir     if (pAttributes.get())
477cdf0e10cSrcweir     {
478cdf0e10cSrcweir         AddRDFa(i_xObject, pAttributes);
479cdf0e10cSrcweir     }
480cdf0e10cSrcweir }
481cdf0e10cSrcweir 
InsertRDFa(uno::Reference<rdf::XRepositorySupplier> const & i_xModel)482cdf0e10cSrcweir void RDFaImportHelper::InsertRDFa(
483cdf0e10cSrcweir     uno::Reference< rdf::XRepositorySupplier> const & i_xModel)
484cdf0e10cSrcweir {
485cdf0e10cSrcweir     OSL_ENSURE(i_xModel.is(), "InsertRDFa: invalid arg: model null");
486cdf0e10cSrcweir     if (!i_xModel.is()) return;
487cdf0e10cSrcweir     const uno::Reference< rdf::XDocumentRepository > xRepository(
488cdf0e10cSrcweir         i_xModel->getRDFRepository(), uno::UNO_QUERY);
489cdf0e10cSrcweir     OSL_ENSURE(xRepository.is(), "InsertRDFa: no DocumentRepository?");
490cdf0e10cSrcweir     if (!xRepository.is()) return;
491cdf0e10cSrcweir     RDFaInserter inserter(GetImport().GetComponentContext(), xRepository);
492cdf0e10cSrcweir     ::std::for_each(m_RDFaEntries.begin(), m_RDFaEntries.end(),
493cdf0e10cSrcweir         ::boost::bind(&RDFaInserter::InsertRDFaEntry, &inserter, _1));
494cdf0e10cSrcweir }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir } // namespace xmloff
497cdf0e10cSrcweir 
498