Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / unoxml / source / rdf / librdf_repository.cxx
blobccf4d87ffedd08301b91afc93fa88cafc7f3a53a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
22 #include <map>
23 #include <memory>
24 #include <mutex>
25 #include <set>
26 #include <string_view>
27 #include <iterator>
28 #include <algorithm>
29 #include <atomic>
31 #include <optional>
33 #include <libxslt/security.h>
35 #include <redland.h>
37 #include <com/sun/star/container/ElementExistException.hpp>
38 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/lang/XInitialization.hpp>
41 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
42 #include <com/sun/star/lang/IllegalArgumentException.hpp>
43 #include <com/sun/star/io/XSeekable.hpp>
44 #include <com/sun/star/text/XTextRange.hpp>
45 #include <com/sun/star/rdf/ParseException.hpp>
46 #include <com/sun/star/rdf/QueryException.hpp>
47 #include <com/sun/star/rdf/RepositoryException.hpp>
48 #include <com/sun/star/rdf/XDocumentRepository.hpp>
49 #include <com/sun/star/rdf/XLiteral.hpp>
50 #include <com/sun/star/rdf/FileFormat.hpp>
51 #include <com/sun/star/rdf/BlankNode.hpp>
52 #include <com/sun/star/rdf/URI.hpp>
53 #include <com/sun/star/rdf/Literal.hpp>
55 #include <rtl/ref.hxx>
56 #include <rtl/ustrbuf.hxx>
57 #include <rtl/ustring.hxx>
58 #include <osl/diagnose.h>
59 #include <cppuhelper/exc_hlp.hxx>
60 #include <cppuhelper/implbase.hxx>
61 #include <cppuhelper/supportsservice.hxx>
62 #include <cppuhelper/weakref.hxx>
64 #include <comphelper/sequence.hxx>
65 #include <comphelper/xmltools.hxx>
67 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
68 #include <utility>
70 /**
71 Implementation of the service com.sun.star.rdf.Repository.
73 This implementation uses the Redland RDF library (librdf).
75 There are several classes involved:
76 librdf_TypeConverter: helper class to convert data types redland <-> uno
77 librdf_Repository: the main repository, does almost all the work
78 librdf_NamedGraph: the XNamedGraph, forwards everything to repository
79 librdf_GraphResult: an XEnumeration<Statement>
80 librdf_QuerySelectResult: an XEnumeration<sequence<XNode>>
84 /// anonymous implementation namespace
85 namespace {
87 class librdf_NamedGraph;
88 class librdf_Repository;
90 using namespace ::com::sun::star;
92 typedef std::map< OUString, ::rtl::Reference<librdf_NamedGraph> >
93 NamedGraphMap_t;
95 const char s_sparql [] = "sparql";
96 const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/";
99 //FIXME: this approach is not ideal. can we use blank nodes instead?
100 bool isInternalContext(librdf_node *i_pNode) noexcept
102 OSL_ENSURE(i_pNode, "isInternalContext: context null");
103 OSL_ENSURE(librdf_node_is_resource(i_pNode),
104 "isInternalContext: context not resource");
105 if (i_pNode) {
106 librdf_uri *pURI(librdf_node_get_uri(i_pNode));
107 OSL_ENSURE(pURI, "isInternalContext: URI null");
108 if (pURI) {
109 unsigned char *pContextURI(librdf_uri_as_string(pURI));
110 assert(pContextURI && "isInternalContext: URI string null");
111 // if prefix matches reserved uri, it is RDFa context
112 if (!strncmp(reinterpret_cast<char *>(pContextURI),
113 s_nsOOo, sizeof(s_nsOOo)-1)) {
114 return true;
117 return false;
119 return true;
123 // n.b.: librdf destructor functions dereference null pointers!
124 // so they need to be wrapped to be usable with std::shared_ptr.
125 void safe_librdf_free_world(librdf_world *const world)
127 if (world) { librdf_free_world(world); }
129 void safe_librdf_free_model(librdf_model *const model)
131 if (model) { librdf_free_model(model); }
133 void safe_librdf_free_node(librdf_node* node)
135 if (node) { librdf_free_node(node); }
137 void safe_librdf_free_parser(librdf_parser *const parser)
139 if (parser) { librdf_free_parser(parser); }
141 void safe_librdf_free_query(librdf_query *const query)
143 if (query) { librdf_free_query(query); }
145 void
146 safe_librdf_free_query_results(librdf_query_results *const query_results)
148 if (query_results) { librdf_free_query_results(query_results); }
150 void safe_librdf_free_serializer(librdf_serializer *const serializer)
152 if (serializer) { librdf_free_serializer(serializer); }
154 void safe_librdf_free_statement(librdf_statement *const statement)
156 if (statement) { librdf_free_statement(statement); }
158 void safe_librdf_free_storage(librdf_storage *const storage)
160 if (storage) { librdf_free_storage(storage); }
162 void safe_librdf_free_stream(librdf_stream *const stream)
164 if (stream) { librdf_free_stream(stream); }
166 void safe_librdf_free_uri(librdf_uri *const uri)
168 if (uri) { librdf_free_uri(uri); }
172 /** converts between librdf types and UNO API types.
174 class librdf_TypeConverter
176 public:
178 // some wrapper classes to temporarily hold values of UNO XNodes
179 struct Node
181 virtual ~Node() {}
183 struct Resource : public Node { };
184 struct URI : public Resource
186 OString const value;
187 explicit URI(OString i_Value)
188 : value(std::move(i_Value))
191 struct BlankNode : public Resource
193 OString const value;
194 explicit BlankNode(OString i_Value)
195 : value(std::move(i_Value))
198 struct Literal : public Node
200 OString const value;
201 OString const language;
202 ::std::optional<OString> const type;
203 Literal(OString i_rValue, OString i_Language,
204 ::std::optional<OString> i_Type)
205 : value(std::move(i_rValue))
206 , language(std::move(i_Language))
207 , type(std::move(i_Type))
210 struct Statement
212 std::shared_ptr<Resource> const pSubject;
213 std::shared_ptr<URI> const pPredicate;
214 std::shared_ptr<Node> const pObject;
215 Statement(std::shared_ptr<Resource> i_pSubject,
216 std::shared_ptr<URI> i_pPredicate,
217 std::shared_ptr<Node> i_pObject)
218 : pSubject(std::move(i_pSubject))
219 , pPredicate(std::move(i_pPredicate))
220 , pObject(std::move(i_pObject))
224 librdf_TypeConverter(
225 uno::Reference< uno::XComponentContext > i_xContext,
226 librdf_Repository &i_rRep)
227 : m_xContext(std::move(i_xContext))
228 , m_rRep(i_rRep)
229 { };
231 librdf_world *createWorld_Lock() const;
232 librdf_storage *createStorage_Lock(librdf_world *i_pWorld) const;
233 librdf_model *createModel_Lock(librdf_world *i_pWorld,
234 librdf_storage * i_pStorage) const;
235 static librdf_uri* mkURI_Lock(librdf_world* i_pWorld,
236 const OString & i_rURI);
237 static librdf_node* mkResource_Lock(librdf_world* i_pWorld,
238 const Resource * i_pResource);
239 static librdf_node* mkNode_Lock(librdf_world* i_pWorld,
240 const Node * i_pNode);
241 static librdf_statement* mkStatement_Lock(librdf_world* i_pWorld,
242 Statement const& i_rStatement);
243 static std::shared_ptr<Resource> extractResource_NoLock(
244 const uno::Reference< rdf::XResource > & i_xResource);
245 static void extractResourceToCacheKey_NoLock(
246 const uno::Reference< rdf::XResource > & i_xResource,
247 OUStringBuffer& rBuf);
248 static std::shared_ptr<Node> extractNode_NoLock(
249 const uno::Reference< rdf::XNode > & i_xNode);
250 static void extractNodeToCacheKey_NoLock(
251 const uno::Reference< rdf::XNode > & i_xNode,
252 OUStringBuffer& rBuffer);
253 static Statement extractStatement_NoLock(
254 const uno::Reference< rdf::XResource > & i_xSubject,
255 const uno::Reference< rdf::XURI > & i_xPredicate,
256 const uno::Reference< rdf::XNode > & i_xObject);
257 uno::Reference<rdf::XURI> convertToXURI(librdf_uri* i_pURI) const;
258 uno::Reference<rdf::XURI> convertToXURI(librdf_node* i_pURI) const;
259 uno::Reference<rdf::XResource>
260 convertToXResource(librdf_node* i_pNode) const;
261 uno::Reference<rdf::XNode> convertToXNode(librdf_node* i_pNode) const;
262 rdf::Statement
263 convertToStatement(librdf_statement* i_pStmt, librdf_node* i_pContext)
264 const;
266 private:
267 uno::Reference< uno::XComponentContext > const m_xContext;
268 librdf_Repository & m_rRep;
272 /** implements the repository service.
274 class librdf_Repository:
275 // private ::cppu::BaseMutex,
276 public ::cppu::WeakImplHelper<
277 lang::XServiceInfo,
278 rdf::XDocumentRepository,
279 lang::XInitialization>
281 public:
283 explicit librdf_Repository(
284 uno::Reference< uno::XComponentContext > const & i_xContext);
285 virtual ~librdf_Repository() override;
287 // css::lang::XServiceInfo:
288 virtual OUString SAL_CALL getImplementationName() override;
289 virtual sal_Bool SAL_CALL supportsService(
290 const OUString & ServiceName) override;
291 virtual uno::Sequence< OUString > SAL_CALL
292 getSupportedServiceNames() override;
294 // css::rdf::XRepository:
295 virtual uno::Reference< rdf::XBlankNode > SAL_CALL createBlankNode() override;
296 virtual uno::Reference<rdf::XNamedGraph> SAL_CALL importGraph(
297 ::sal_Int16 i_Format,
298 const uno::Reference< io::XInputStream > & i_xInStream,
299 const uno::Reference< rdf::XURI > & i_xGraphName,
300 const uno::Reference< rdf::XURI > & i_xBaseURI) override;
301 virtual void SAL_CALL exportGraph(::sal_Int16 i_Format,
302 const uno::Reference< io::XOutputStream > & i_xOutStream,
303 const uno::Reference< rdf::XURI > & i_xGraphName,
304 const uno::Reference< rdf::XURI > & i_xBaseURI) override;
305 virtual uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
306 getGraphNames() override;
307 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL getGraph(
308 const uno::Reference< rdf::XURI > & i_xGraphName) override;
309 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL createGraph(
310 const uno::Reference< rdf::XURI > & i_xGraphName) override;
311 virtual void SAL_CALL destroyGraph(
312 const uno::Reference< rdf::XURI > & i_xGraphName) override;
313 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
314 const uno::Reference< rdf::XResource > & i_xSubject,
315 const uno::Reference< rdf::XURI > & i_xPredicate,
316 const uno::Reference< rdf::XNode > & i_xObject) override;
317 virtual uno::Reference< rdf::XQuerySelectResult > SAL_CALL
318 querySelect(const OUString & i_rQuery) override;
319 virtual uno::Reference< container::XEnumeration > SAL_CALL
320 queryConstruct(const OUString & i_rQuery) override;
321 virtual sal_Bool SAL_CALL queryAsk(const OUString & i_rQuery) override;
323 // css::rdf::XDocumentRepository:
324 virtual void SAL_CALL setStatementRDFa(
325 const uno::Reference< rdf::XResource > & i_xSubject,
326 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
327 const uno::Reference< rdf::XMetadatable > & i_xObject,
328 const OUString & i_rRDFaContent,
329 const uno::Reference< rdf::XURI > & i_xRDFaDatatype) override;
330 virtual void SAL_CALL removeStatementRDFa(
331 const uno::Reference< rdf::XMetadatable > & i_xElement) override;
332 virtual beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
333 getStatementRDFa(uno::Reference< rdf::XMetadatable > const& i_xElement) override;
334 virtual uno::Reference< container::XEnumeration > SAL_CALL
335 getStatementsRDFa(
336 const uno::Reference< rdf::XResource > & i_xSubject,
337 const uno::Reference< rdf::XURI > & i_xPredicate,
338 const uno::Reference< rdf::XNode > & i_xObject) override;
340 // css::lang::XInitialization:
341 virtual void SAL_CALL initialize(
342 const uno::Sequence< css::uno::Any > & i_rArguments) override;
344 // XNamedGraph forwards ---------------------------------------------
345 NamedGraphMap_t::iterator clearGraph_NoLock(
346 const OUString & i_rGraphName,
347 bool i_Internal = false );
348 NamedGraphMap_t::iterator clearGraph_Lock(
349 const OUString & i_rGraphName,
350 bool i_Internal);
351 void addStatementGraph_NoLock(
352 const uno::Reference< rdf::XResource > & i_xSubject,
353 const uno::Reference< rdf::XURI > & i_xPredicate,
354 const uno::Reference< rdf::XNode > & i_xObject,
355 const uno::Reference< rdf::XURI > & i_xName );
356 // throw (uno::RuntimeException, lang::IllegalArgumentException,
357 // container::NoSuchElementException, rdf::RepositoryException);
358 void addStatementGraph_Lock(
359 librdf_TypeConverter::Statement const& i_rStatement,
360 OUString const& i_rGraphName,
361 bool i_Internal);
362 void removeStatementsGraph_NoLock(
363 const uno::Reference< rdf::XResource > & i_xSubject,
364 const uno::Reference< rdf::XURI > & i_xPredicate,
365 const uno::Reference< rdf::XNode > & i_xObject,
366 const uno::Reference< rdf::XURI > & i_xName );
367 // throw (uno::RuntimeException, lang::IllegalArgumentException,
368 // container::NoSuchElementException, rdf::RepositoryException);
369 std::vector<rdf::Statement> getStatementsGraph_NoLock(
370 const uno::Reference< rdf::XResource > & i_xSubject,
371 const uno::Reference< rdf::XURI > & i_xPredicate,
372 const uno::Reference< rdf::XNode > & i_xObject,
373 const uno::Reference< rdf::XURI > & i_xName,
374 bool i_Internal = false );
375 // throw (uno::RuntimeException, lang::IllegalArgumentException,
376 // container::NoSuchElementException, rdf::RepositoryException);
378 const librdf_TypeConverter& getTypeConverter() const { return m_TypeConverter; };
380 private:
382 librdf_Repository(librdf_Repository const&) = delete;
383 librdf_Repository& operator=(librdf_Repository const&) = delete;
385 /// this is const, no need to lock m_aMutex to access it
386 uno::Reference< uno::XComponentContext > const m_xContext;
388 /// librdf global data
389 /** N.B.: The redland documentation gives the impression that you can have
390 as many librdf_worlds as you like. This is true in the same sense
391 that you can physically be in as many places as you like.
392 Well, you can, just not at the same time.
393 The ugly truth is that destroying a librdf_world kills a bunch
394 of static variables; other librdf_worlds become very unhappy
395 when they access these.
396 And of course this is not documented anywhere that I could find.
397 So we allocate a single world, and refcount that.
399 static std::shared_ptr<librdf_world> m_pWorld;
400 /// refcount
401 static sal_uInt32 m_NumInstances;
402 /// mutex for m_pWorld - redland is not as threadsafe as is often claimed
403 static std::mutex m_aMutex;
405 // NB: sequence of the shared pointers is important!
406 /// librdf repository storage
407 std::shared_ptr<librdf_storage> m_pStorage;
408 /// librdf repository model
409 std::shared_ptr<librdf_model> m_pModel;
411 /// all named graphs
412 NamedGraphMap_t m_NamedGraphs;
414 /// type conversion helper - stateless
415 librdf_TypeConverter m_TypeConverter;
417 /// set of xml:ids of elements with xhtml:content
418 ::std::set< OUString > m_RDFaXHTMLContentSet;
422 /** result of operations that return a graph, i.e.,
423 an XEnumeration of statements.
425 class librdf_GraphResult:
426 public ::cppu::WeakImplHelper<
427 container::XEnumeration>
429 public:
431 librdf_GraphResult(librdf_Repository *i_pRepository,
432 std::mutex & i_rMutex,
433 std::shared_ptr<librdf_stream> i_pStream,
434 std::shared_ptr<librdf_node> i_pContext,
435 std::shared_ptr<librdf_query> i_pQuery =
436 std::shared_ptr<librdf_query>() )
437 : m_xRep(i_pRepository)
438 , m_rMutex(i_rMutex)
439 , m_pQuery(std::move(i_pQuery))
440 , m_pContext(std::move(i_pContext))
441 , m_pStream(std::move(i_pStream))
442 { };
444 virtual ~librdf_GraphResult() override
446 std::scoped_lock g(m_rMutex); // lock mutex when destroying members
447 const_cast<std::shared_ptr<librdf_stream>& >(m_pStream).reset();
448 const_cast<std::shared_ptr<librdf_node>& >(m_pContext).reset();
449 const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset();
452 // css::container::XEnumeration:
453 virtual sal_Bool SAL_CALL hasMoreElements() override;
454 virtual uno::Any SAL_CALL nextElement() override;
456 private:
458 librdf_GraphResult(librdf_GraphResult const&) = delete;
459 librdf_GraphResult& operator=(librdf_GraphResult const&) = delete;
461 // NB: this is not a weak pointer: streams _must_ be deleted before the
462 // storage they point into, so we keep the repository alive here
463 // also, sequence is important: the stream must be destroyed first.
464 ::rtl::Reference< librdf_Repository > m_xRep;
465 // needed for synchronizing access to librdf (it doesn't do win32 threading)
466 std::mutex & m_rMutex;
467 // the query (in case this is a result of a graph query)
468 // not that the redland documentation spells this out explicitly, but
469 // queries must be freed only after all the results are completely read
470 std::shared_ptr<librdf_query> const m_pQuery;
471 std::shared_ptr<librdf_node> const m_pContext;
472 std::shared_ptr<librdf_stream> const m_pStream;
474 librdf_node* getContext_Lock() const;
478 // css::container::XEnumeration:
479 sal_Bool SAL_CALL
480 librdf_GraphResult::hasMoreElements()
482 std::scoped_lock g(m_rMutex);
483 return m_pStream && !librdf_stream_end(m_pStream.get());
486 librdf_node* librdf_GraphResult::getContext_Lock() const
488 if (!m_pStream || librdf_stream_end(m_pStream.get()))
489 return nullptr;
490 librdf_node *pCtxt(
491 #if LIBRDF_VERSION >= 10012
492 librdf_stream_get_context2(m_pStream.get()) );
493 #else
494 static_cast<librdf_node *>(librdf_stream_get_context(m_pStream.get())) );
495 #endif
496 if (pCtxt)
497 return pCtxt;
498 return m_pContext.get();
501 css::uno::Any SAL_CALL
502 librdf_GraphResult::nextElement()
504 std::scoped_lock g(m_rMutex);
505 if (m_pStream && librdf_stream_end(m_pStream.get())) {
506 throw container::NoSuchElementException();
508 librdf_node * pCtxt = getContext_Lock();
510 librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) );
511 if (!pStmt) {
512 rdf::QueryException e(
513 "librdf_GraphResult::nextElement: "
514 "librdf_stream_get_object failed", *this);
515 throw lang::WrappedTargetException(
516 "librdf_GraphResult::nextElement: "
517 "librdf_stream_get_object failed", *this,
518 uno::Any(e));
520 // NB: pCtxt may be null here if this is result of a graph query
521 if (pCtxt && isInternalContext(pCtxt)) {
522 pCtxt = nullptr; // XML ID context is implementation detail!
524 rdf::Statement Stmt(
525 m_xRep->getTypeConverter().convertToStatement(pStmt, pCtxt) );
526 // NB: this will invalidate current item.
527 librdf_stream_next(m_pStream.get());
528 return uno::Any(Stmt);
532 /** result of operations that return a graph, i.e.,
533 an XEnumeration of statements.
535 class librdf_GraphResult2:
536 public ::cppu::WeakImplHelper<
537 container::XEnumeration>
539 public:
541 librdf_GraphResult2(std::vector<rdf::Statement> statements)
542 : m_vStatements(std::move(statements))
543 { };
545 // css::container::XEnumeration:
546 virtual sal_Bool SAL_CALL hasMoreElements() override;
547 virtual uno::Any SAL_CALL nextElement() override;
549 private:
551 std::vector<rdf::Statement> m_vStatements;
552 std::atomic<std::size_t> m_nIndex = 0;
556 // css::container::XEnumeration:
557 sal_Bool SAL_CALL
558 librdf_GraphResult2::hasMoreElements()
560 return m_nIndex < m_vStatements.size();
563 css::uno::Any SAL_CALL
564 librdf_GraphResult2::nextElement()
566 std::size_t const n = m_nIndex++;
567 if (m_vStatements.size() <= n)
569 m_nIndex = m_vStatements.size(); // avoid overflow
570 throw container::NoSuchElementException();
572 return uno::Any(m_vStatements[n]);
575 /** result of tuple queries ("SELECT").
577 class librdf_QuerySelectResult:
578 public ::cppu::WeakImplHelper<
579 rdf::XQuerySelectResult>
581 public:
583 librdf_QuerySelectResult(librdf_Repository *i_pRepository,
584 std::mutex & i_rMutex,
585 std::shared_ptr<librdf_query> i_pQuery,
586 std::shared_ptr<librdf_query_results> i_pQueryResult,
587 uno::Sequence< OUString > const& i_rBindingNames )
588 : m_xRep(i_pRepository)
589 , m_rMutex(i_rMutex)
590 , m_pQuery(std::move(i_pQuery))
591 , m_pQueryResult(std::move(i_pQueryResult))
592 , m_BindingNames(i_rBindingNames)
593 { };
595 virtual ~librdf_QuerySelectResult() override
597 std::scoped_lock g(m_rMutex); // lock mutex when destroying members
598 const_cast<std::shared_ptr<librdf_query_results>& >(m_pQueryResult)
599 .reset();
600 const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset();
603 // css::container::XEnumeration:
604 virtual sal_Bool SAL_CALL hasMoreElements() override;
605 virtual uno::Any SAL_CALL nextElement() override;
607 // css::rdf::XQuerySelectResult:
608 virtual uno::Sequence< OUString > SAL_CALL getBindingNames() override;
610 private:
612 librdf_QuerySelectResult(librdf_QuerySelectResult const&) = delete;
613 librdf_QuerySelectResult& operator=(librdf_QuerySelectResult const&) = delete;
615 // NB: this is not a weak pointer: streams _must_ be deleted before the
616 // storage they point into, so we keep the repository alive here
617 // also, sequence is important: the stream must be destroyed first.
618 ::rtl::Reference< librdf_Repository > m_xRep;
619 // needed for synchronizing access to librdf (it doesn't do win32 threading)
620 std::mutex & m_rMutex;
621 // not that the redland documentation spells this out explicitly, but
622 // queries must be freed only after all the results are completely read
623 std::shared_ptr<librdf_query> const m_pQuery;
624 std::shared_ptr<librdf_query_results> const m_pQueryResult;
625 uno::Sequence< OUString > const m_BindingNames;
629 // css::container::XEnumeration:
630 sal_Bool SAL_CALL
631 librdf_QuerySelectResult::hasMoreElements()
633 std::scoped_lock g(m_rMutex);
634 return !librdf_query_results_finished(m_pQueryResult.get());
637 class NodeArray : private std::vector<librdf_node*>
639 public:
640 NodeArray(int cnt) : std::vector<librdf_node*>(cnt) {}
642 ~NodeArray() noexcept
644 std::for_each(begin(), end(), safe_librdf_free_node);
647 using std::vector<librdf_node*>::data;
648 using std::vector<librdf_node*>::operator[];
651 css::uno::Any SAL_CALL
652 librdf_QuerySelectResult::nextElement()
654 std::scoped_lock g(m_rMutex);
655 if (librdf_query_results_finished(m_pQueryResult.get())) {
656 throw container::NoSuchElementException();
658 sal_Int32 count(m_BindingNames.getLength());
659 OSL_ENSURE(count >= 0, "negative length?");
660 NodeArray aNodes(count);
661 if (librdf_query_results_get_bindings(m_pQueryResult.get(), nullptr,
662 aNodes.data()))
664 rdf::QueryException e(
665 "librdf_QuerySelectResult::nextElement: "
666 "librdf_query_results_get_bindings failed", *this);
667 throw lang::WrappedTargetException(
668 "librdf_QuerySelectResult::nextElement: "
669 "librdf_query_results_get_bindings failed", *this,
670 uno::Any(e));
672 uno::Sequence< uno::Reference< rdf::XNode > > ret(count);
673 auto retRange = asNonConstRange(ret);
674 for (int i = 0; i < count; ++i) {
675 retRange[i] = m_xRep->getTypeConverter().convertToXNode(aNodes[i]);
677 // NB: this will invalidate current item.
678 librdf_query_results_next(m_pQueryResult.get());
679 return uno::Any(ret);
682 // css::rdf::XQuerySelectResult:
683 uno::Sequence< OUString > SAL_CALL
684 librdf_QuerySelectResult::getBindingNames()
686 // const - no lock needed
687 return m_BindingNames;
691 /** represents a named graph, and forwards all the work to repository.
693 class librdf_NamedGraph:
694 public ::cppu::WeakImplHelper<
695 rdf::XNamedGraph>
697 public:
698 librdf_NamedGraph(librdf_Repository * i_pRep,
699 uno::Reference<rdf::XURI> i_xName)
700 : m_wRep(i_pRep)
701 , m_pRep(i_pRep)
702 , m_xName(std::move(i_xName))
703 { };
705 // css::rdf::XNode:
706 virtual OUString SAL_CALL getStringValue() override;
708 // css::rdf::XURI:
709 virtual OUString SAL_CALL getNamespace() override;
710 virtual OUString SAL_CALL getLocalName() override;
712 // css::rdf::XNamedGraph:
713 virtual uno::Reference<rdf::XURI> SAL_CALL getName() override;
714 virtual void SAL_CALL clear() override;
715 virtual void SAL_CALL addStatement(
716 const uno::Reference< rdf::XResource > & i_xSubject,
717 const uno::Reference< rdf::XURI > & i_xPredicate,
718 const uno::Reference< rdf::XNode > & i_xObject) override;
719 virtual void SAL_CALL removeStatements(
720 const uno::Reference< rdf::XResource > & i_xSubject,
721 const uno::Reference< rdf::XURI > & i_xPredicate,
722 const uno::Reference< rdf::XNode > & i_xObject) override;
723 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
724 const uno::Reference< rdf::XResource > & i_xSubject,
725 const uno::Reference< rdf::XURI > & i_xPredicate,
726 const uno::Reference< rdf::XNode > & i_xObject) override;
728 private:
730 librdf_NamedGraph(librdf_NamedGraph const&) = delete;
731 librdf_NamedGraph& operator=(librdf_NamedGraph const&) = delete;
733 static OUString createCacheKey_NoLock(
734 const uno::Reference< rdf::XResource > & i_xSubject,
735 const uno::Reference< rdf::XURI > & i_xPredicate,
736 const uno::Reference< rdf::XNode > & i_xObject);
738 /// weak reference: this is needed to check if m_pRep is valid
739 uno::WeakReference< rdf::XRepository > const m_wRep;
740 librdf_Repository *const m_pRep;
741 uno::Reference< rdf::XURI > const m_xName;
743 /// Querying is rather slow, so cache the results.
744 std::map<OUString, std::vector<rdf::Statement>> m_aStatementsCache;
745 std::mutex m_CacheMutex;
749 // css::rdf::XNode:
750 OUString SAL_CALL librdf_NamedGraph::getStringValue()
752 return m_xName->getStringValue();
755 // css::rdf::XURI:
756 OUString SAL_CALL librdf_NamedGraph::getNamespace()
758 return m_xName->getNamespace();
761 OUString SAL_CALL librdf_NamedGraph::getLocalName()
763 return m_xName->getLocalName();
766 // css::rdf::XNamedGraph:
767 uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName()
769 return m_xName;
772 void SAL_CALL librdf_NamedGraph::clear()
774 uno::Reference< rdf::XRepository > xRep( m_wRep );
775 if (!xRep.is()) {
776 throw rdf::RepositoryException(
777 "librdf_NamedGraph::clear: repository is gone", *this);
779 const OUString contextU( m_xName->getStringValue() );
780 try {
781 m_pRep->clearGraph_NoLock(contextU);
782 } catch (lang::IllegalArgumentException & ex) {
783 css::uno::Any anyEx = cppu::getCaughtException();
784 throw lang::WrappedTargetRuntimeException( ex.Message,
785 *this, anyEx );
787 std::unique_lock g(m_CacheMutex);
788 m_aStatementsCache.clear();
791 void SAL_CALL librdf_NamedGraph::addStatement(
792 const uno::Reference< rdf::XResource > & i_xSubject,
793 const uno::Reference< rdf::XURI > & i_xPredicate,
794 const uno::Reference< rdf::XNode > & i_xObject)
796 uno::Reference< rdf::XRepository > xRep( m_wRep );
797 if (!xRep.is()) {
798 throw rdf::RepositoryException(
799 "librdf_NamedGraph::addStatement: repository is gone", *this);
802 std::unique_lock g(m_CacheMutex);
803 m_aStatementsCache.clear();
805 m_pRep->addStatementGraph_NoLock(
806 i_xSubject, i_xPredicate, i_xObject, m_xName);
809 void SAL_CALL librdf_NamedGraph::removeStatements(
810 const uno::Reference< rdf::XResource > & i_xSubject,
811 const uno::Reference< rdf::XURI > & i_xPredicate,
812 const uno::Reference< rdf::XNode > & i_xObject)
814 uno::Reference< rdf::XRepository > xRep( m_wRep );
815 if (!xRep.is()) {
816 throw rdf::RepositoryException(
817 "librdf_NamedGraph::removeStatements: repository is gone", *this);
820 std::unique_lock g(m_CacheMutex);
821 m_aStatementsCache.clear();
823 m_pRep->removeStatementsGraph_NoLock(
824 i_xSubject, i_xPredicate, i_xObject, m_xName);
827 OUString librdf_NamedGraph::createCacheKey_NoLock(
828 const uno::Reference< rdf::XResource > & i_xSubject,
829 const uno::Reference< rdf::XURI > & i_xPredicate,
830 const uno::Reference< rdf::XNode > & i_xObject)
832 OUStringBuffer cacheKey(256);
833 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xSubject, cacheKey);
834 cacheKey.append("\t");
835 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xPredicate, cacheKey);
836 cacheKey.append("\t");
837 librdf_TypeConverter::extractNodeToCacheKey_NoLock(i_xObject, cacheKey);
838 return cacheKey.makeStringAndClear();
841 uno::Reference< container::XEnumeration > SAL_CALL
842 librdf_NamedGraph::getStatements(
843 const uno::Reference< rdf::XResource > & i_xSubject,
844 const uno::Reference< rdf::XURI > & i_xPredicate,
845 const uno::Reference< rdf::XNode > & i_xObject)
847 OUString cacheKey = createCacheKey_NoLock(i_xSubject, i_xPredicate, i_xObject);
849 std::unique_lock g(m_CacheMutex);
850 auto it = m_aStatementsCache.find(cacheKey);
851 if (it != m_aStatementsCache.end()) {
852 return new librdf_GraphResult2(it->second);
856 uno::Reference< rdf::XRepository > xRep( m_wRep );
857 if (!xRep.is()) {
858 throw rdf::RepositoryException(
859 "librdf_NamedGraph::getStatements: repository is gone", *this);
861 std::vector<rdf::Statement> vStatements = m_pRep->getStatementsGraph_NoLock(
862 i_xSubject, i_xPredicate, i_xObject, m_xName);
865 std::unique_lock g(m_CacheMutex);
866 m_aStatementsCache.emplace(cacheKey, vStatements);
868 return new librdf_GraphResult2(std::move(vStatements));
872 std::shared_ptr<librdf_world> librdf_Repository::m_pWorld;
873 sal_uInt32 librdf_Repository::m_NumInstances = 0;
874 std::mutex librdf_Repository::m_aMutex;
876 librdf_Repository::librdf_Repository(
877 uno::Reference< uno::XComponentContext > const & i_xContext)
878 : /*BaseMutex(),*/ m_xContext(i_xContext)
879 // m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ),
880 , m_pStorage(static_cast<librdf_storage*>(nullptr), safe_librdf_free_storage)
881 , m_pModel (static_cast<librdf_model *>(nullptr), safe_librdf_free_model )
882 , m_TypeConverter(i_xContext, *this)
884 OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context");
886 std::scoped_lock g(m_aMutex);
887 if (!m_NumInstances++) {
888 m_pWorld.reset(m_TypeConverter.createWorld_Lock(),
889 safe_librdf_free_world);
893 librdf_Repository::~librdf_Repository()
895 std::scoped_lock g(m_aMutex);
897 // must destroy these before world!
898 m_pModel.reset();
899 m_pStorage.reset();
901 // FIXME: so it turns out that calling librdf_free_world will
902 // (via raptor_sax2_finish) call xmlCleanupParser, which will
903 // free libxml2's globals! ARRRGH!!! => never call librdf_free_world
904 #if 0
905 if (!--m_NumInstances) {
906 m_pWorld.reset();
908 #endif
911 // com.sun.star.uno.XServiceInfo:
912 OUString SAL_CALL librdf_Repository::getImplementationName()
914 return "librdf_Repository";
917 sal_Bool SAL_CALL librdf_Repository::supportsService(
918 OUString const & serviceName)
920 return cppu::supportsService(this, serviceName);
923 uno::Sequence< OUString > SAL_CALL
924 librdf_Repository::getSupportedServiceNames()
926 return { "com.sun.star.rdf.Repository" };
929 // css::rdf::XRepository:
930 uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode()
932 std::scoped_lock g(m_aMutex);
933 const std::shared_ptr<librdf_node> pNode(
934 librdf_new_node_from_blank_identifier(m_pWorld.get(), nullptr),
935 safe_librdf_free_node);
936 if (!pNode) {
937 throw uno::RuntimeException(
938 "librdf_Repository::createBlankNode: "
939 "librdf_new_node_from_blank_identifier failed", *this);
941 const unsigned char * id (librdf_node_get_blank_identifier(pNode.get()));
942 if (!id) {
943 throw uno::RuntimeException(
944 "librdf_Repository::createBlankNode: "
945 "librdf_node_get_blank_identifier failed", *this);
947 const OUString nodeID(OUString::createFromAscii(
948 reinterpret_cast<const char *>(id)));
949 try {
950 return rdf::BlankNode::create(m_xContext, nodeID);
951 } catch (const lang::IllegalArgumentException &) {
952 css::uno::Any anyEx = cppu::getCaughtException();
953 throw lang::WrappedTargetRuntimeException(
954 "librdf_Repository::createBlankNode: "
955 "illegal blank node label", *this, anyEx);
959 //void SAL_CALL
960 uno::Reference<rdf::XNamedGraph> SAL_CALL
961 librdf_Repository::importGraph(::sal_Int16 i_Format,
962 const uno::Reference< io::XInputStream > & i_xInStream,
963 const uno::Reference< rdf::XURI > & i_xGraphName,
964 const uno::Reference< rdf::XURI > & i_xBaseURI)
966 if (!i_xInStream.is()) {
967 throw lang::IllegalArgumentException(
968 "librdf_Repository::importGraph: stream is null", *this, 1);
970 //FIXME: other formats
971 if (i_Format != rdf::FileFormat::RDF_XML) {
972 throw datatransfer::UnsupportedFlavorException(
973 "librdf_Repository::importGraph: file format not supported", *this);
975 if (!i_xGraphName.is()) {
976 throw lang::IllegalArgumentException(
977 "librdf_Repository::importGraph: graph name is null", *this, 2);
979 if (i_xGraphName->getStringValue().startsWith(s_nsOOo))
981 throw lang::IllegalArgumentException(
982 "librdf_Repository::importGraph: URI is reserved", *this, 0);
984 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
985 throw lang::IllegalArgumentException(
986 "librdf_Repository::importGraph: base URI is null", *this, 3);
988 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
989 const OUString baseURIU( i_xBaseURI->getStringValue() );
990 if (baseURIU.indexOf('#') >= 0) {
991 throw lang::IllegalArgumentException(
992 "librdf_Repository::importGraph: base URI is not absolute", *this, 3);
995 const OUString contextU( i_xGraphName->getStringValue() );
997 uno::Sequence<sal_Int8> buf;
998 uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
999 // UGLY: if only redland could read streams...
1000 const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
1001 // exceptions are propagated
1002 i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
1004 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1006 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1007 throw container::ElementExistException(
1008 "librdf_Repository::importGraph: graph with given URI exists", *this);
1010 const OString context(
1011 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1013 const std::shared_ptr<librdf_node> pContext(
1014 librdf_new_node_from_uri_string(m_pWorld.get(),
1015 reinterpret_cast<const unsigned char*> (context.getStr())),
1016 safe_librdf_free_node);
1017 if (!pContext) {
1018 throw uno::RuntimeException(
1019 "librdf_Repository::importGraph: librdf_new_node_from_uri_string failed", *this);
1022 const OString baseURI(
1023 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1024 const std::shared_ptr<librdf_uri> pBaseURI(
1025 librdf_new_uri(m_pWorld.get(),
1026 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1027 safe_librdf_free_uri);
1028 if (!pBaseURI) {
1029 throw uno::RuntimeException( "librdf_Repository::importGraph: librdf_new_uri failed", *this);
1032 const std::shared_ptr<librdf_parser> pParser(
1033 librdf_new_parser(m_pWorld.get(), "rdfxml", nullptr, nullptr),
1034 safe_librdf_free_parser);
1035 if (!pParser) {
1036 throw uno::RuntimeException(
1037 "librdf_Repository::importGraph: "
1038 "librdf_new_parser failed", *this);
1041 const std::shared_ptr<librdf_stream> pStream(
1042 librdf_parser_parse_counted_string_as_stream(pParser.get(),
1043 reinterpret_cast<const unsigned char*>(buf.getConstArray()),
1044 buf.getLength(), pBaseURI.get()),
1045 safe_librdf_free_stream);
1046 if (!pStream) {
1047 throw rdf::ParseException(
1048 "librdf_Repository::importGraph: "
1049 "librdf_parser_parse_counted_string_as_stream failed", *this);
1051 rtl::Reference<librdf_NamedGraph> const pGraph(
1052 new librdf_NamedGraph(this, i_xGraphName));
1053 m_NamedGraphs.insert(std::make_pair(contextU, pGraph));
1054 if (librdf_model_context_add_statements(m_pModel.get(),
1055 pContext.get(), pStream.get())) {
1056 throw rdf::RepositoryException(
1057 "librdf_Repository::importGraph: "
1058 "librdf_model_context_add_statements failed", *this);
1061 return pGraph;
1064 void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
1066 if (!length)
1067 return;
1069 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream,
1070 uno::UNO_QUERY);
1072 bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData();
1074 // exceptions are propagated
1075 if (!bAddChaff)
1077 const uno::Sequence<sal_Int8> buf(
1078 reinterpret_cast<sal_Int8*>(pBuffer), length);
1079 rStream->writeBytes(buf);
1081 else
1083 unsigned char *postcomment =
1084 reinterpret_cast<unsigned char*>(strchr(reinterpret_cast<char*>(pBuffer), '\n'));
1085 if (postcomment != nullptr)
1087 ++postcomment;
1089 size_t preamblelen = postcomment - pBuffer;
1091 uno::Sequence<sal_Int8> buf(
1092 reinterpret_cast<sal_Int8*>(pBuffer), preamblelen);
1093 rStream->writeBytes(buf);
1095 OString aComment =
1096 "<!--" +
1097 comphelper::xml::makeXMLChaff() +
1098 "-->";
1100 buf = uno::Sequence<sal_Int8>(
1101 reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength());
1102 rStream->writeBytes(buf);
1104 buf = uno::Sequence<sal_Int8>(
1105 reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen);
1106 rStream->writeBytes(buf);
1111 void SAL_CALL
1112 librdf_Repository::exportGraph(::sal_Int16 i_Format,
1113 const uno::Reference< io::XOutputStream > & i_xOutStream,
1114 const uno::Reference< rdf::XURI > & i_xGraphName,
1115 const uno::Reference< rdf::XURI > & i_xBaseURI)
1117 if (!i_xOutStream.is()) {
1118 throw lang::IllegalArgumentException(
1119 "librdf_Repository::exportGraph: stream is null", *this, 1);
1121 // FIXME: other formats
1122 if (i_Format != rdf::FileFormat::RDF_XML) {
1123 throw datatransfer::UnsupportedFlavorException(
1124 "librdf_Repository::exportGraph: "
1125 "file format not supported", *this);
1127 if (!i_xGraphName.is()) {
1128 throw lang::IllegalArgumentException(
1129 "librdf_Repository::exportGraph: "
1130 "graph name is null", *this, 2);
1132 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
1133 throw lang::IllegalArgumentException(
1134 "librdf_Repository::exportGraph: "
1135 "base URI is null", *this, 3);
1137 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
1138 const OUString baseURIU( i_xBaseURI->getStringValue() );
1139 if (baseURIU.indexOf('#') >= 0) {
1140 throw lang::IllegalArgumentException(
1141 "librdf_Repository::exportGraph: "
1142 "base URI is not absolute", *this, 3);
1145 const OUString contextU( i_xGraphName->getStringValue() );
1147 std::unique_lock g(m_aMutex); // don't call i_x* with mutex locked
1149 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1150 throw container::NoSuchElementException(
1151 "librdf_Repository::exportGraph: "
1152 "no graph with given URI exists", *this);
1154 const OString context(
1155 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1157 const std::shared_ptr<librdf_node> pContext(
1158 librdf_new_node_from_uri_string(m_pWorld.get(),
1159 reinterpret_cast<const unsigned char*> (context.getStr())),
1160 safe_librdf_free_node);
1161 if (!pContext) {
1162 throw uno::RuntimeException(
1163 "librdf_Repository::exportGraph: "
1164 "librdf_new_node_from_uri_string failed", *this);
1166 const OString baseURI(
1167 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1168 const std::shared_ptr<librdf_uri> pBaseURI(
1169 librdf_new_uri(m_pWorld.get(),
1170 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1171 safe_librdf_free_uri);
1172 if (!pBaseURI) {
1173 throw uno::RuntimeException(
1174 "librdf_Repository::exportGraph: "
1175 "librdf_new_uri failed", *this);
1178 const std::shared_ptr<librdf_stream> pStream(
1179 librdf_model_context_as_stream(m_pModel.get(), pContext.get()),
1180 safe_librdf_free_stream);
1181 if (!pStream) {
1182 throw rdf::RepositoryException(
1183 "librdf_Repository::exportGraph: "
1184 "librdf_model_context_as_stream failed", *this);
1186 const char * const format("rdfxml");
1187 // #i116443#: abbrev breaks when certain URIs are used as data types
1188 // const char *format("rdfxml-abbrev");
1189 const std::shared_ptr<librdf_serializer> pSerializer(
1190 librdf_new_serializer(m_pWorld.get(), format, nullptr, nullptr),
1191 safe_librdf_free_serializer);
1192 if (!pSerializer) {
1193 throw uno::RuntimeException(
1194 "librdf_Repository::exportGraph: "
1195 "librdf_new_serializer failed", *this);
1198 const std::shared_ptr<librdf_uri> pRelativeURI(
1199 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1200 ("http://feature.librdf.org/raptor-relativeURIs")),
1201 safe_librdf_free_uri);
1202 const std::shared_ptr<librdf_uri> pWriteBaseURI(
1203 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1204 ("http://feature.librdf.org/raptor-writeBaseURI")),
1205 safe_librdf_free_uri);
1206 const std::shared_ptr<librdf_node> p0(
1207 librdf_new_node_from_literal(m_pWorld.get(),
1208 reinterpret_cast<const unsigned char*> ("0"), nullptr, 0),
1209 safe_librdf_free_node);
1210 const std::shared_ptr<librdf_node> p1(
1211 librdf_new_node_from_literal(m_pWorld.get(),
1212 reinterpret_cast<const unsigned char*> ("1"), nullptr, 0),
1213 safe_librdf_free_node);
1214 if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) {
1215 throw uno::RuntimeException(
1216 "librdf_Repository::exportGraph: "
1217 "librdf_new_uri or librdf_new_node_from_literal failed", *this);
1220 // make URIs relative to base URI
1221 if (librdf_serializer_set_feature(pSerializer.get(),
1222 pRelativeURI.get(), p1.get()))
1224 throw uno::RuntimeException(
1225 "librdf_Repository::exportGraph: "
1226 "librdf_serializer_set_feature relativeURIs failed", *this);
1228 // but do not write the base URI to the file!
1229 if (librdf_serializer_set_feature(pSerializer.get(),
1230 pWriteBaseURI.get(), p0.get()))
1232 throw uno::RuntimeException(
1233 "librdf_Repository::exportGraph: "
1234 "librdf_serializer_set_feature writeBaseURI failed", *this);
1237 size_t length;
1238 const std::shared_ptr<unsigned char> pBuf(
1239 librdf_serializer_serialize_stream_to_counted_string(
1240 pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free);
1241 if (!pBuf) {
1242 throw rdf::RepositoryException(
1243 "librdf_Repository::exportGraph: "
1244 "librdf_serializer_serialize_stream_to_counted_string failed",
1245 *this);
1248 g.unlock(); // release Mutex before calling i_xOutStream methods
1250 addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
1253 uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
1254 librdf_Repository::getGraphNames()
1256 std::scoped_lock g(m_aMutex);
1257 ::std::vector< uno::Reference<rdf::XURI> > ret;
1258 std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(),
1259 std::back_inserter(ret),
1260 [](std::pair<OUString, ::rtl::Reference<librdf_NamedGraph>> const& it)
1261 { return it.second->getName(); });
1262 return comphelper::containerToSequence(ret);
1265 uno::Reference< rdf::XNamedGraph > SAL_CALL
1266 librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1268 if (!i_xGraphName.is()) {
1269 throw lang::IllegalArgumentException(
1270 "librdf_Repository::getGraph: URI is null", *this, 0);
1272 const OUString contextU( i_xGraphName->getStringValue() );
1274 std::scoped_lock g(m_aMutex);
1275 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
1276 if (iter != m_NamedGraphs.end()) {
1277 return iter->second;
1278 } else {
1279 return nullptr;
1283 uno::Reference< rdf::XNamedGraph > SAL_CALL
1284 librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1286 if (!i_xGraphName.is()) {
1287 throw lang::IllegalArgumentException(
1288 "librdf_Repository::createGraph: URI is null", *this, 0);
1291 const OUString contextU( i_xGraphName->getStringValue() );
1292 if (contextU.startsWith(s_nsOOo))
1294 throw lang::IllegalArgumentException(
1295 "librdf_Repository::createGraph: URI is reserved", *this, 0);
1298 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1300 // NB: librdf does not have a concept of graphs as such;
1301 // a librdf named graph exists iff the model contains a statement with
1302 // the graph name as context
1304 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1305 throw container::ElementExistException(
1306 "librdf_Repository::createGraph: graph with given URI exists", *this);
1308 m_NamedGraphs.insert(std::make_pair(contextU,
1309 new librdf_NamedGraph(this, i_xGraphName)));
1310 return m_NamedGraphs.find(contextU)->second;
1313 void SAL_CALL
1314 librdf_Repository::destroyGraph(
1315 const uno::Reference< rdf::XURI > & i_xGraphName)
1317 if (!i_xGraphName.is()) {
1318 throw lang::IllegalArgumentException(
1319 "librdf_Repository::destroyGraph: URI is null", *this, 0);
1321 const OUString contextU( i_xGraphName->getStringValue() );
1323 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1325 const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) );
1326 m_NamedGraphs.erase(iter);
1329 bool isMetadatableWithoutMetadata(
1330 uno::Reference<uno::XInterface> const & i_xNode)
1332 const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY );
1333 return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty());
1336 uno::Reference< container::XEnumeration > SAL_CALL
1337 librdf_Repository::getStatements(
1338 const uno::Reference< rdf::XResource > & i_xSubject,
1339 const uno::Reference< rdf::XURI > & i_xPredicate,
1340 const uno::Reference< rdf::XNode > & i_xObject)
1342 if (isMetadatableWithoutMetadata(i_xSubject) ||
1343 isMetadatableWithoutMetadata(i_xPredicate) ||
1344 isMetadatableWithoutMetadata(i_xObject))
1346 return new librdf_GraphResult(this, m_aMutex,
1347 std::shared_ptr<librdf_stream>(),
1348 std::shared_ptr<librdf_node>());
1351 librdf_TypeConverter::Statement const stmt(
1352 librdf_TypeConverter::extractStatement_NoLock(
1353 i_xSubject, i_xPredicate, i_xObject));
1355 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1357 const std::shared_ptr<librdf_statement> pStatement(
1358 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1359 safe_librdf_free_statement);
1360 OSL_ENSURE(pStatement, "mkStatement failed");
1362 const std::shared_ptr<librdf_stream> pStream(
1363 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1364 safe_librdf_free_stream);
1365 if (!pStream) {
1366 throw rdf::RepositoryException(
1367 "librdf_Repository::getStatements: "
1368 "librdf_model_find_statements failed", *this);
1371 return new librdf_GraphResult(this, m_aMutex, pStream,
1372 std::shared_ptr<librdf_node>());
1376 uno::Reference< rdf::XQuerySelectResult > SAL_CALL
1377 librdf_Repository::querySelect(const OUString & i_rQuery)
1379 std::scoped_lock g(m_aMutex);
1380 const OString query(
1381 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1382 const std::shared_ptr<librdf_query> pQuery(
1383 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1384 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1385 safe_librdf_free_query);
1386 if (!pQuery) {
1387 throw rdf::QueryException(
1388 "librdf_Repository::querySelect: "
1389 "librdf_new_query failed", *this);
1391 const std::shared_ptr<librdf_query_results> pResults(
1392 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1393 safe_librdf_free_query_results);
1394 if (!pResults || !librdf_query_results_is_bindings(pResults.get())) {
1395 throw rdf::QueryException(
1396 "librdf_Repository::querySelect: "
1397 "query result is null or not bindings", *this);
1400 const int count( librdf_query_results_get_bindings_count(pResults.get()) );
1401 if (count < 0) {
1402 throw rdf::QueryException(
1403 "librdf_Repository::querySelect: "
1404 "librdf_query_results_get_bindings_count failed", *this);
1406 uno::Sequence< OUString > names(count);
1407 auto namesRange = asNonConstRange(names);
1408 for (int i = 0; i < count; ++i) {
1409 const char* name( librdf_query_results_get_binding_name(
1410 pResults.get(), i) );
1411 if (!name) {
1412 throw rdf::QueryException(
1413 "librdf_Repository::querySelect: binding is null", *this);
1416 namesRange[i] = OUString::createFromAscii(name);
1419 return new librdf_QuerySelectResult(this, m_aMutex,
1420 pQuery, pResults, names);
1423 uno::Reference< container::XEnumeration > SAL_CALL
1424 librdf_Repository::queryConstruct(const OUString & i_rQuery)
1426 std::scoped_lock g(m_aMutex);
1427 const OString query(
1428 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1429 const std::shared_ptr<librdf_query> pQuery(
1430 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1431 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1432 safe_librdf_free_query);
1433 if (!pQuery) {
1434 throw rdf::QueryException(
1435 "librdf_Repository::queryConstruct: "
1436 "librdf_new_query failed", *this);
1438 const std::shared_ptr<librdf_query_results> pResults(
1439 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1440 safe_librdf_free_query_results);
1441 if (!pResults || !librdf_query_results_is_graph(pResults.get())) {
1442 throw rdf::QueryException(
1443 "librdf_Repository::queryConstruct: "
1444 "query result is null or not graph", *this);
1446 const std::shared_ptr<librdf_stream> pStream(
1447 librdf_query_results_as_stream(pResults.get()),
1448 safe_librdf_free_stream);
1449 if (!pStream) {
1450 throw rdf::QueryException(
1451 "librdf_Repository::queryConstruct: "
1452 "librdf_query_results_as_stream failed", *this);
1455 return new librdf_GraphResult(this, m_aMutex, pStream,
1456 std::shared_ptr<librdf_node>(), pQuery);
1459 sal_Bool SAL_CALL
1460 librdf_Repository::queryAsk(const OUString & i_rQuery)
1462 std::scoped_lock g(m_aMutex);
1464 const OString query(
1465 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1466 const std::shared_ptr<librdf_query> pQuery(
1467 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1468 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1469 safe_librdf_free_query);
1470 if (!pQuery) {
1471 throw rdf::QueryException(
1472 "librdf_Repository::queryAsk: "
1473 "librdf_new_query failed", *this);
1475 const std::shared_ptr<librdf_query_results> pResults(
1476 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1477 safe_librdf_free_query_results);
1478 if (!pResults || !librdf_query_results_is_boolean(pResults.get())) {
1479 throw rdf::QueryException(
1480 "librdf_Repository::queryAsk: "
1481 "query result is null or not boolean", *this);
1483 return bool(librdf_query_results_get_boolean(pResults.get()));
1486 // css::rdf::XDocumentRepository:
1487 void SAL_CALL librdf_Repository::setStatementRDFa(
1488 const uno::Reference< rdf::XResource > & i_xSubject,
1489 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
1490 const uno::Reference< rdf::XMetadatable > & i_xObject,
1491 const OUString & i_rRDFaContent,
1492 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
1494 if (!i_xSubject.is()) {
1495 throw lang::IllegalArgumentException(
1496 "librdf_Repository::setStatementRDFa: Subject is null", *this, 0);
1498 if (!i_rPredicates.hasElements()) {
1499 throw lang::IllegalArgumentException(
1500 "librdf_Repository::setStatementRDFa: no Predicates",
1501 *this, 1);
1503 if (std::any_of(i_rPredicates.begin(), i_rPredicates.end(),
1504 [](const uno::Reference< rdf::XURI >& rPredicate) { return !rPredicate.is(); })) {
1505 throw lang::IllegalArgumentException(
1506 "librdf_Repository::setStatementRDFa: Predicate is null", *this, 1);
1508 if (!i_xObject.is()) {
1509 throw lang::IllegalArgumentException(
1510 "librdf_Repository::setStatementRDFa: Object is null", *this, 2);
1512 const uno::Reference<lang::XServiceInfo> xService(i_xObject,
1513 uno::UNO_QUERY_THROW);
1514 uno::Reference<text::XTextRange> xTextRange;
1515 if (xService->supportsService("com.sun.star.table.Cell") ||
1516 xService->supportsService("com.sun.star.text.CellProperties") || // for writer
1517 xService->supportsService("com.sun.star.text.Paragraph"))
1519 xTextRange.set(i_xObject, uno::UNO_QUERY_THROW);
1521 else if (xService->supportsService("com.sun.star.text.Bookmark") ||
1522 xService->supportsService("com.sun.star.text.InContentMetadata"))
1524 const uno::Reference<text::XTextContent> xTextContent(i_xObject,
1525 uno::UNO_QUERY_THROW);
1526 xTextRange = xTextContent->getAnchor();
1528 if (!xTextRange.is()) {
1529 throw lang::IllegalArgumentException(
1530 "librdf_Repository::setStatementRDFa: "
1531 "Object does not support RDFa", *this, 2);
1533 // ensure that the metadatable has an XML ID
1534 i_xObject->ensureMetadataReference();
1535 const beans::StringPair mdref( i_xObject->getMetadataReference() );
1536 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1537 throw uno::RuntimeException(
1538 "librdf_Repository::setStatementRDFa: "
1539 "ensureMetadataReference did not", *this);
1541 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1542 OUString const sContext(s_nsOOo + sXmlId);
1543 OUString const content( (i_rRDFaContent.isEmpty())
1544 ? xTextRange->getString()
1545 : i_rRDFaContent );
1546 uno::Reference<rdf::XNode> xContent;
1547 try {
1548 if (i_xRDFaDatatype.is()) {
1549 xContent.set(rdf::Literal::createWithType(m_xContext,
1550 content, i_xRDFaDatatype),
1551 uno::UNO_QUERY_THROW);
1552 } else {
1553 xContent.set(rdf::Literal::create(m_xContext, content),
1554 uno::UNO_QUERY_THROW);
1556 } catch (const lang::IllegalArgumentException &) {
1557 css::uno::Any anyEx = cppu::getCaughtException();
1558 throw lang::WrappedTargetRuntimeException(
1559 "librdf_Repository::setStatementRDFa: "
1560 "cannot create literal", *this, anyEx);
1563 std::shared_ptr<librdf_TypeConverter::Resource> const pSubject(
1564 librdf_TypeConverter::extractResource_NoLock(i_xSubject));
1565 std::shared_ptr<librdf_TypeConverter::Node> const pContent(
1566 librdf_TypeConverter::extractNode_NoLock(xContent));
1567 ::std::vector< std::shared_ptr<librdf_TypeConverter::Resource> >
1568 predicates;
1569 ::std::transform(i_rPredicates.begin(), i_rPredicates.end(),
1570 ::std::back_inserter(predicates),
1571 [](uno::Reference<rdf::XURI> const& xURI)
1572 { return librdf_TypeConverter::extractResource_NoLock(xURI); });
1574 removeStatementRDFa(i_xObject); // not atomic with insertion?
1576 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1578 if (i_rRDFaContent.isEmpty()) {
1579 m_RDFaXHTMLContentSet.erase(sXmlId);
1580 } else {
1581 m_RDFaXHTMLContentSet.insert(sXmlId);
1585 for (const auto& rPredicatePtr : predicates)
1587 addStatementGraph_Lock(
1588 librdf_TypeConverter::Statement(pSubject,
1589 std::dynamic_pointer_cast<librdf_TypeConverter::URI>(rPredicatePtr),
1590 pContent),
1591 sContext, true);
1594 catch (const container::NoSuchElementException&)
1596 css::uno::Any anyEx = cppu::getCaughtException();
1597 throw lang::WrappedTargetRuntimeException(
1598 "librdf_Repository::setStatementRDFa: "
1599 "cannot addStatementGraph", *this, anyEx);
1603 void SAL_CALL librdf_Repository::removeStatementRDFa(
1604 const uno::Reference< rdf::XMetadatable > & i_xElement)
1606 if (!i_xElement.is()) {
1607 throw lang::IllegalArgumentException(
1608 "librdf_Repository::removeStatementRDFa: Element is null",
1609 *this, 0);
1612 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1613 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1614 return; // nothing to do...
1617 OUString const sXmlId(s_nsOOo + mdref.First + "#" + mdref.Second);
1619 clearGraph_NoLock(sXmlId, true);
1622 beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
1623 librdf_Repository::getStatementRDFa(
1624 const uno::Reference< rdf::XMetadatable > & i_xElement)
1626 if (!i_xElement.is()) {
1627 throw lang::IllegalArgumentException(
1628 "librdf_Repository::getStatementRDFa: Element is null", *this, 0);
1630 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1631 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1632 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >();
1634 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1635 uno::Reference<rdf::XURI> xXmlId;
1636 try {
1637 xXmlId.set( rdf::URI::create(m_xContext, s_nsOOo + sXmlId),
1638 uno::UNO_SET_THROW);
1639 } catch (const lang::IllegalArgumentException &) {
1640 css::uno::Any anyEx = cppu::getCaughtException();
1641 throw lang::WrappedTargetRuntimeException(
1642 "librdf_Repository::getStatementRDFa: "
1643 "cannot create URI for XML ID", *this, anyEx);
1646 ::std::vector< rdf::Statement > ret;
1649 ret = getStatementsGraph_NoLock(nullptr, nullptr, nullptr, xXmlId, true);
1651 catch (const container::NoSuchElementException&)
1653 css::uno::Any anyEx = cppu::getCaughtException();
1654 throw lang::WrappedTargetRuntimeException(
1655 "librdf_Repository::getStatementRDFa: "
1656 "cannot getStatementsGraph", *this, anyEx);
1659 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1661 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
1662 comphelper::containerToSequence(ret), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
1665 extern "C"
1666 librdf_statement *rdfa_context_stream_map_handler(
1667 librdf_stream *i_pStream, void *, librdf_statement *i_pStatement)
1669 OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null");
1670 if (i_pStream) {
1671 librdf_node *pCtxt(
1672 #if LIBRDF_VERSION >= 10012
1673 librdf_stream_get_context2(i_pStream) );
1674 #else
1675 static_cast<librdf_node *>(librdf_stream_get_context(i_pStream)) );
1676 #endif
1677 OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null");
1678 if (pCtxt && isInternalContext(pCtxt)) {
1679 return i_pStatement;
1682 return nullptr;
1685 uno::Reference< container::XEnumeration > SAL_CALL
1686 librdf_Repository::getStatementsRDFa(
1687 const uno::Reference< rdf::XResource > & i_xSubject,
1688 const uno::Reference< rdf::XURI > & i_xPredicate,
1689 const uno::Reference< rdf::XNode > & i_xObject)
1691 if (isMetadatableWithoutMetadata(i_xSubject) ||
1692 isMetadatableWithoutMetadata(i_xPredicate) ||
1693 isMetadatableWithoutMetadata(i_xObject))
1695 return new librdf_GraphResult(this, m_aMutex,
1696 std::shared_ptr<librdf_stream>(),
1697 std::shared_ptr<librdf_node>());
1700 librdf_TypeConverter::Statement const stmt(
1701 librdf_TypeConverter::extractStatement_NoLock(
1702 i_xSubject, i_xPredicate, i_xObject));
1704 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1706 const std::shared_ptr<librdf_statement> pStatement(
1707 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1708 safe_librdf_free_statement);
1709 OSL_ENSURE(pStatement, "mkStatement failed");
1711 const std::shared_ptr<librdf_stream> pStream(
1712 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1713 safe_librdf_free_stream);
1714 if (!pStream) {
1715 throw rdf::RepositoryException(
1716 "librdf_Repository::getStatementsRDFa: "
1717 "librdf_model_find_statements failed", *this);
1720 if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler,
1721 nullptr, nullptr)) {
1722 throw rdf::RepositoryException(
1723 "librdf_Repository::getStatementsRDFa: "
1724 "librdf_stream_add_map failed", *this);
1727 return new librdf_GraphResult(this, m_aMutex, pStream,
1728 std::shared_ptr<librdf_node>());
1731 // css::lang::XInitialization:
1732 void SAL_CALL librdf_Repository::initialize(
1733 const uno::Sequence< css::uno::Any > &)
1735 std::scoped_lock g(m_aMutex);
1737 // m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
1738 m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()),
1739 safe_librdf_free_storage);
1740 m_pModel.reset(m_TypeConverter.createModel_Lock(
1741 m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
1744 NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock(
1745 OUString const& i_rGraphName, bool i_Internal)
1746 // throw (uno::RuntimeException, container::NoSuchElementException,
1747 // rdf::RepositoryException)
1749 std::scoped_lock g(m_aMutex);
1751 return clearGraph_Lock(i_rGraphName, i_Internal);
1754 NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock(
1755 OUString const& i_rGraphName, bool i_Internal)
1757 // internal: must be called with mutex locked!
1758 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) );
1759 if (!i_Internal && iter == m_NamedGraphs.end()) {
1760 throw container::NoSuchElementException(
1761 "librdf_Repository::clearGraph: "
1762 "no graph with given URI exists", *this);
1764 const OString context(
1765 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1767 const std::shared_ptr<librdf_node> pContext(
1768 librdf_new_node_from_uri_string(m_pWorld.get(),
1769 reinterpret_cast<const unsigned char*> (context.getStr())),
1770 safe_librdf_free_node);
1771 if (!pContext) {
1772 throw uno::RuntimeException(
1773 "librdf_Repository::clearGraph: "
1774 "librdf_new_node_from_uri_string failed", *this);
1776 if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get()))
1778 throw rdf::RepositoryException(
1779 "librdf_Repository::clearGraph: "
1780 "librdf_model_context_remove_statements failed", *this);
1782 return iter;
1785 void librdf_Repository::addStatementGraph_NoLock(
1786 const uno::Reference< rdf::XResource > & i_xSubject,
1787 const uno::Reference< rdf::XURI > & i_xPredicate,
1788 const uno::Reference< rdf::XNode > & i_xObject,
1789 const uno::Reference< rdf::XURI > & i_xGraphName)
1790 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1791 // container::NoSuchElementException, rdf::RepositoryException)
1793 if (!i_xSubject.is()) {
1794 throw lang::IllegalArgumentException(
1795 "librdf_Repository::addStatement: Subject is null", *this, 0);
1797 if (!i_xPredicate.is()) {
1798 throw lang::IllegalArgumentException(
1799 "librdf_Repository::addStatement: Predicate is null",
1800 *this, 1);
1802 if (!i_xObject.is()) {
1803 throw lang::IllegalArgumentException(
1804 "librdf_Repository::addStatement: Object is null", *this, 2);
1807 librdf_TypeConverter::Statement const stmt(
1808 librdf_TypeConverter::extractStatement_NoLock(
1809 i_xSubject, i_xPredicate, i_xObject));
1811 const OUString contextU( i_xGraphName->getStringValue() );
1813 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1815 addStatementGraph_Lock(stmt, contextU, false/*i_Internal*/);
1818 void librdf_Repository::addStatementGraph_Lock(
1819 librdf_TypeConverter::Statement const& i_rStatement,
1820 OUString const& i_rGraphName,
1821 bool i_Internal)
1823 if (!i_Internal
1824 && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end()))
1826 throw container::NoSuchElementException(
1827 "librdf_Repository::addStatement: "
1828 "no graph with given URI exists", *this);
1830 const OString context(
1831 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1833 const std::shared_ptr<librdf_node> pContext(
1834 librdf_new_node_from_uri_string(m_pWorld.get(),
1835 reinterpret_cast<const unsigned char*> (context.getStr())),
1836 safe_librdf_free_node);
1837 if (!pContext) {
1838 throw uno::RuntimeException(
1839 "librdf_Repository::addStatement: "
1840 "librdf_new_node_from_uri_string failed", *this);
1842 const std::shared_ptr<librdf_statement> pStatement(
1843 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), i_rStatement),
1844 safe_librdf_free_statement);
1845 OSL_ENSURE(pStatement, "mkStatement failed");
1847 // Test for duplicate statement
1848 // librdf_model_add_statement disallows duplicates while
1849 // librdf_model_context_add_statement allows duplicates
1851 const std::shared_ptr<librdf_stream> pStream(
1852 librdf_model_find_statements_in_context(m_pModel.get(),
1853 pStatement.get(), pContext.get()),
1854 safe_librdf_free_stream);
1855 if (pStream && !librdf_stream_end(pStream.get()))
1856 return;
1859 if (librdf_model_context_add_statement(m_pModel.get(),
1860 pContext.get(), pStatement.get())) {
1861 throw rdf::RepositoryException(
1862 "librdf_Repository::addStatement: "
1863 "librdf_model_context_add_statement failed", *this);
1867 void librdf_Repository::removeStatementsGraph_NoLock(
1868 const uno::Reference< rdf::XResource > & i_xSubject,
1869 const uno::Reference< rdf::XURI > & i_xPredicate,
1870 const uno::Reference< rdf::XNode > & i_xObject,
1871 const uno::Reference< rdf::XURI > & i_xGraphName)
1872 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1873 // container::NoSuchElementException, rdf::RepositoryException)
1875 if (isMetadatableWithoutMetadata(i_xSubject) ||
1876 isMetadatableWithoutMetadata(i_xPredicate) ||
1877 isMetadatableWithoutMetadata(i_xObject))
1879 return;
1882 librdf_TypeConverter::Statement const stmt(
1883 librdf_TypeConverter::extractStatement_NoLock(
1884 i_xSubject, i_xPredicate, i_xObject));
1885 const OUString contextU( i_xGraphName->getStringValue() );
1887 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1889 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1890 throw container::NoSuchElementException(
1891 "librdf_Repository::removeStatements: "
1892 "no graph with given URI exists", *this);
1894 const OString context(
1895 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1897 const std::shared_ptr<librdf_node> pContext(
1898 librdf_new_node_from_uri_string(m_pWorld.get(),
1899 reinterpret_cast<const unsigned char*> (context.getStr())),
1900 safe_librdf_free_node);
1901 if (!pContext) {
1902 throw uno::RuntimeException(
1903 "librdf_Repository::removeStatements: "
1904 "librdf_new_node_from_uri_string failed", *this);
1906 const std::shared_ptr<librdf_statement> pStatement(
1907 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1908 safe_librdf_free_statement);
1909 OSL_ENSURE(pStatement, "mkStatement failed");
1911 const std::shared_ptr<librdf_stream> pStream(
1912 librdf_model_find_statements_in_context(m_pModel.get(),
1913 pStatement.get(), pContext.get()),
1914 safe_librdf_free_stream);
1915 if (!pStream) {
1916 throw rdf::RepositoryException(
1917 "librdf_Repository::removeStatements: "
1918 "librdf_model_find_statements_in_context failed", *this);
1921 if (librdf_stream_end(pStream.get()))
1922 return;
1924 do {
1925 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
1926 if (!pStmt) {
1927 throw rdf::RepositoryException(
1928 "librdf_Repository::removeStatements: "
1929 "librdf_stream_get_object failed", *this);
1931 if (librdf_model_context_remove_statement(m_pModel.get(),
1932 pContext.get(), pStmt)) {
1933 throw rdf::RepositoryException(
1934 "librdf_Repository::removeStatements: "
1935 "librdf_model_context_remove_statement failed", *this);
1937 } while (!librdf_stream_next(pStream.get()));
1940 std::vector<rdf::Statement>
1941 librdf_Repository::getStatementsGraph_NoLock(
1942 const uno::Reference< rdf::XResource > & i_xSubject,
1943 const uno::Reference< rdf::XURI > & i_xPredicate,
1944 const uno::Reference< rdf::XNode > & i_xObject,
1945 const uno::Reference< rdf::XURI > & i_xGraphName,
1946 bool i_Internal)
1947 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1948 // container::NoSuchElementException, rdf::RepositoryException)
1950 std::vector<rdf::Statement> ret;
1952 // N.B.: if any of subject, predicate, object is an XMetadatable, and
1953 // has no metadata reference, then there cannot be any node in the graph
1954 // representing it; in order to prevent side effect
1955 // (ensureMetadataReference), check for this condition and return
1956 if (isMetadatableWithoutMetadata(i_xSubject) ||
1957 isMetadatableWithoutMetadata(i_xPredicate) ||
1958 isMetadatableWithoutMetadata(i_xObject))
1960 return ret;
1963 librdf_TypeConverter::Statement const stmt(
1964 librdf_TypeConverter::extractStatement_NoLock(
1965 i_xSubject, i_xPredicate, i_xObject));
1966 const OUString contextU( i_xGraphName->getStringValue() );
1968 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1970 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1971 throw container::NoSuchElementException(
1972 "librdf_Repository::getStatements: "
1973 "no graph with given URI exists", *this);
1975 const OString context(
1976 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1978 const std::shared_ptr<librdf_node> pContext(
1979 librdf_new_node_from_uri_string(m_pWorld.get(),
1980 reinterpret_cast<const unsigned char*> (context.getStr())),
1981 safe_librdf_free_node);
1982 if (!pContext) {
1983 throw uno::RuntimeException(
1984 "librdf_Repository::getStatements: "
1985 "librdf_new_node_from_uri_string failed", *this);
1987 const std::shared_ptr<librdf_statement> pStatement(
1988 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1989 safe_librdf_free_statement);
1990 OSL_ENSURE(pStatement, "mkStatement failed");
1992 const std::shared_ptr<librdf_stream> pStream(
1993 librdf_model_find_statements_in_context(m_pModel.get(),
1994 pStatement.get(), pContext.get()),
1995 safe_librdf_free_stream);
1996 if (!pStream) {
1997 throw rdf::RepositoryException(
1998 "librdf_Repository::getStatements: "
1999 "librdf_model_find_statements_in_context failed", *this);
2002 librdf_node *pCtxt1(
2003 #if LIBRDF_VERSION >= 10012
2004 librdf_stream_get_context2(pStream.get()) );
2005 #else
2006 static_cast<librdf_node *>(librdf_stream_get_context(pStream.get())) );
2007 #endif
2008 while (!librdf_stream_end(pStream.get()))
2010 auto pCtxt = pCtxt1;
2011 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
2012 if (!pStmt) {
2013 rdf::QueryException e(
2014 "librdf_GraphResult::nextElement: "
2015 "librdf_stream_get_object failed", *this);
2016 throw lang::WrappedTargetException(
2017 "librdf_GraphResult::nextElement: "
2018 "librdf_stream_get_object failed", *this,
2019 uno::Any(e));
2021 // NB: pCtxt may be null here if this is result of a graph query
2022 if (pCtxt && isInternalContext(pCtxt)) {
2023 pCtxt = nullptr; // XML ID context is implementation detail!
2026 ret.emplace_back(
2027 getTypeConverter().convertToStatement(pStmt, pCtxt) );
2029 // NB: this will invalidate current item.
2030 librdf_stream_next(pStream.get());
2033 return ret;
2036 extern "C"
2037 void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld)
2039 // fdo#64672 prevent raptor from setting global libxml2 error handlers
2040 raptor_world_set_flag(pRaptorWorld,
2041 RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE, 0);
2042 raptor_world_set_flag(pRaptorWorld,
2043 RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0);
2046 librdf_world *librdf_TypeConverter::createWorld_Lock() const
2048 // create and initialize world
2049 librdf_world *pWorld( librdf_new_world() );
2050 if (!pWorld) {
2051 throw uno::RuntimeException(
2052 "librdf_TypeConverter::createWorld: librdf_new_world failed",
2053 m_rRep);
2055 librdf_world_set_raptor_init_handler(pWorld, nullptr, &librdf_raptor_init);
2056 //FIXME logger, digest, features?
2057 xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs();
2058 librdf_world_open(pWorld);
2059 xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs();
2060 if (newprefs != origprefs) {
2061 // #i110523# restore libxslt global configuration
2062 // (gratuitously overwritten by raptor_init_parser_grddl_common)
2063 // (this is the only reason unordf is linked against libxslt)
2064 xsltSetDefaultSecurityPrefs(origprefs);
2066 return pWorld;
2069 librdf_storage *
2070 librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const
2072 librdf_storage *pStorage(
2073 // librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
2074 librdf_new_storage(i_pWorld, "hashes", nullptr,
2075 "contexts='yes',hash-type='memory'") );
2076 if (!pStorage) {
2077 throw uno::RuntimeException(
2078 "librdf_TypeConverter::createStorage: librdf_new_storage failed",
2079 m_rRep);
2081 return pStorage;
2084 librdf_model *librdf_TypeConverter::createModel_Lock(
2085 librdf_world *i_pWorld, librdf_storage * i_pStorage) const
2087 librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, nullptr) );
2088 if (!pRepository) {
2089 throw uno::RuntimeException(
2090 "librdf_TypeConverter::createModel: librdf_new_model failed",
2091 m_rRep);
2093 //FIXME
2094 #if 0
2096 librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS));
2097 librdf_node * contexts = librdf_model_get_feature(repository, ctxt);
2098 if (!contexts)
2099 throw;
2100 std::cout << "value of contexts feature: ";
2101 prtNode(contexts);
2102 std::cout << std::endl;
2103 // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...);
2104 safe_librdf_free_node(contexts);
2105 safe_librdf_free_uri(ctxt);
2107 #endif
2108 return pRepository;
2111 // this does NOT create a node, only URI
2112 librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld,
2113 OString const& i_rURI)
2115 librdf_uri *pURI( librdf_new_uri(i_pWorld,
2116 reinterpret_cast<const unsigned char *>(i_rURI.getStr())));
2117 if (!pURI) {
2118 throw uno::RuntimeException(
2119 "librdf_TypeConverter::mkURI: librdf_new_uri failed", nullptr);
2121 return pURI;
2124 // extract blank or URI node - call without Mutex locked
2125 std::shared_ptr<librdf_TypeConverter::Resource>
2126 librdf_TypeConverter::extractResource_NoLock(
2127 const uno::Reference< rdf::XResource > & i_xResource)
2129 if (!i_xResource.is()) {
2130 return std::shared_ptr<Resource>();
2132 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2133 if (xBlankNode.is()) {
2134 const OString label(
2135 OUStringToOString(xBlankNode->getStringValue(),
2136 RTL_TEXTENCODING_UTF8) );
2137 return std::make_shared<BlankNode>(label);
2138 } else { // assumption: everything else is URI
2139 const OString uri(
2140 OUStringToOString(i_xResource->getStringValue(),
2141 RTL_TEXTENCODING_UTF8) );
2142 return std::make_shared<URI>(uri);
2146 void
2147 librdf_TypeConverter::extractResourceToCacheKey_NoLock(
2148 const uno::Reference< rdf::XResource > & i_xResource, OUStringBuffer& rBuffer)
2150 if (!i_xResource.is()) {
2151 return;
2153 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2154 if (xBlankNode.is()) {
2155 rBuffer.append("BlankNode " + xBlankNode->getStringValue());
2156 } else { // assumption: everything else is URI
2157 rBuffer.append("URI " + i_xResource->getStringValue());
2161 // create blank or URI node
2162 librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld,
2163 Resource const*const i_pResource)
2165 if (!i_pResource) return nullptr;
2166 BlankNode const*const pBlankNode(
2167 dynamic_cast<BlankNode const*>(i_pResource));
2168 if (pBlankNode) {
2169 librdf_node *pNode(
2170 librdf_new_node_from_blank_identifier(i_pWorld,
2171 reinterpret_cast<const unsigned char*>(
2172 pBlankNode->value.getStr())));
2173 if (!pNode) {
2174 throw uno::RuntimeException(
2175 "librdf_TypeConverter::mkResource: "
2176 "librdf_new_node_from_blank_identifier failed", nullptr);
2178 return pNode;
2179 } else { // assumption: everything else is URI
2180 URI const*const pURI(dynamic_cast<URI const*>(i_pResource));
2181 assert(pURI);
2182 librdf_node *pNode(
2183 librdf_new_node_from_uri_string(i_pWorld,
2184 reinterpret_cast<const unsigned char*>(pURI->value.getStr())));
2185 if (!pNode) {
2186 throw uno::RuntimeException(
2187 "librdf_TypeConverter::mkResource: "
2188 "librdf_new_node_from_uri_string failed", nullptr);
2190 return pNode;
2194 // extract blank or URI or literal node - call without Mutex locked
2195 std::shared_ptr<librdf_TypeConverter::Node>
2196 librdf_TypeConverter::extractNode_NoLock(
2197 const uno::Reference< rdf::XNode > & i_xNode)
2199 if (!i_xNode.is()) {
2200 return std::shared_ptr<Node>();
2202 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2203 if (xResource.is()) {
2204 return extractResource_NoLock(xResource);
2206 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2207 OSL_ENSURE(xLiteral.is(),
2208 "mkNode: someone invented a new rdf.XNode and did not tell me");
2209 if (!xLiteral.is()) {
2210 return std::shared_ptr<Node>();
2212 const OString val(
2213 OUStringToOString(xLiteral->getValue(),
2214 RTL_TEXTENCODING_UTF8) );
2215 const OString lang(
2216 OUStringToOString(xLiteral->getLanguage(),
2217 RTL_TEXTENCODING_UTF8) );
2218 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2219 std::optional<OString> type;
2220 if (xType.is())
2222 type =
2223 OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8);
2225 return std::make_shared<Literal>(val, lang, type);
2228 // extract blank or URI or literal node - call without Mutex locked
2229 void
2230 librdf_TypeConverter::extractNodeToCacheKey_NoLock(
2231 const uno::Reference< rdf::XNode > & i_xNode,
2232 OUStringBuffer& rBuffer)
2234 if (!i_xNode.is()) {
2235 return;
2237 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2238 if (xResource.is()) {
2239 return extractResourceToCacheKey_NoLock(xResource, rBuffer);
2241 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2242 OSL_ENSURE(xLiteral.is(),
2243 "mkNode: someone invented a new rdf.XNode and did not tell me");
2244 if (!xLiteral.is()) {
2245 return;
2247 rBuffer.append("Literal " + xLiteral->getValue() + "\t" + xLiteral->getLanguage());
2248 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2249 if (xType.is())
2250 rBuffer.append("\t" + xType->getStringValue());
2253 // create blank or URI or literal node
2254 librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld,
2255 Node const*const i_pNode)
2257 if (!i_pNode) return nullptr;
2258 Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode));
2259 if (pResource) {
2260 return mkResource_Lock(i_pWorld, pResource);
2263 Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode));
2264 assert(pLiteral);
2265 librdf_node * ret(nullptr);
2266 if (pLiteral->language.isEmpty()) {
2267 if (!pLiteral->type) {
2268 ret = librdf_new_node_from_literal(i_pWorld,
2269 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2270 , nullptr, 0);
2271 } else {
2272 const std::shared_ptr<librdf_uri> pDatatype(
2273 mkURI_Lock(i_pWorld, *pLiteral->type),
2274 safe_librdf_free_uri);
2275 ret = librdf_new_node_from_typed_literal(i_pWorld,
2276 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2277 , nullptr, pDatatype.get());
2279 } else {
2280 if (!pLiteral->type) {
2281 ret = librdf_new_node_from_literal(i_pWorld,
2282 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2283 , pLiteral->language.getStr(), 0);
2284 } else {
2285 OSL_FAIL("mkNode: invalid literal");
2286 return nullptr;
2289 if (!ret) {
2290 throw uno::RuntimeException(
2291 "librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed", nullptr);
2293 return ret;
2296 // extract statement - call without Mutex locked
2297 librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock(
2298 const uno::Reference< rdf::XResource > & i_xSubject,
2299 const uno::Reference< rdf::XURI > & i_xPredicate,
2300 const uno::Reference< rdf::XNode > & i_xObject)
2302 std::shared_ptr<Resource> const pSubject(
2303 extractResource_NoLock(i_xSubject));
2304 std::shared_ptr<URI> const pPredicate(
2305 std::dynamic_pointer_cast<URI>(extractResource_NoLock(i_xPredicate)));
2306 std::shared_ptr<Node> const pObject(extractNode_NoLock(i_xObject));
2307 return Statement(pSubject, pPredicate, pObject);
2310 librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld,
2311 Statement const& i_rStatement)
2313 librdf_node *const pSubject(
2314 mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) );
2315 librdf_node* pPredicate(nullptr);
2316 librdf_node* pObject(nullptr);
2317 try {
2318 pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get());
2319 try {
2320 pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get());
2321 } catch (...) {
2322 safe_librdf_free_node(pPredicate);
2323 throw;
2325 } catch (...) {
2326 safe_librdf_free_node(pSubject);
2327 throw;
2329 // NB: this takes ownership of the nodes! (which is really ugly)
2330 librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld,
2331 pSubject, pPredicate, pObject) );
2332 if (!pStatement) {
2333 throw uno::RuntimeException(
2334 "librdf_TypeConverter::mkStatement: "
2335 "librdf_new_statement_from_nodes failed", nullptr);
2337 return pStatement;
2340 uno::Reference<rdf::XURI>
2341 librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const
2343 if (!i_pURI) return nullptr;
2344 const unsigned char* uri( librdf_uri_as_string(i_pURI) );
2345 if (!uri) {
2346 throw uno::RuntimeException(
2347 "librdf_TypeConverter::convertToXURI: "
2348 "librdf_uri_as_string failed", m_rRep);
2350 OUString uriU( OStringToOUString(
2351 std::string_view(reinterpret_cast<const char*>(uri)),
2352 RTL_TEXTENCODING_UTF8) );
2353 try {
2354 return rdf::URI::create(m_xContext, uriU);
2355 } catch (const lang::IllegalArgumentException &) {
2356 css::uno::Any anyEx = cppu::getCaughtException();
2357 throw lang::WrappedTargetRuntimeException(
2358 "librdf_TypeConverter::convertToXURI: "
2359 "illegal uri", m_rRep, anyEx);
2363 uno::Reference<rdf::XURI>
2364 librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const
2366 if (!i_pNode) return nullptr;
2367 if (librdf_node_is_resource(i_pNode)) {
2368 librdf_uri* pURI( librdf_node_get_uri(i_pNode) );
2369 if (!pURI) {
2370 throw uno::RuntimeException(
2371 "librdf_TypeConverter::convertToXURI: "
2372 "resource has no uri", m_rRep);
2374 return convertToXURI(pURI);
2375 } else {
2376 OSL_FAIL("convertToXURI: unknown librdf_node");
2377 return nullptr;
2381 uno::Reference<rdf::XResource>
2382 librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const
2384 if (!i_pNode) return nullptr;
2385 if (librdf_node_is_blank(i_pNode)) {
2386 const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) );
2387 if (!label) {
2388 throw uno::RuntimeException(
2389 "librdf_TypeConverter::convertToXResource: "
2390 "blank node has no label", m_rRep);
2392 OUString labelU( OStringToOUString(
2393 std::string_view(reinterpret_cast<const char*>(label)),
2394 RTL_TEXTENCODING_UTF8) );
2395 try {
2396 return rdf::BlankNode::create(m_xContext, labelU);
2397 } catch (const lang::IllegalArgumentException &) {
2398 css::uno::Any anyEx = cppu::getCaughtException();
2399 throw lang::WrappedTargetRuntimeException(
2400 "librdf_TypeConverter::convertToXResource: "
2401 "illegal blank node label", m_rRep, anyEx);
2403 } else {
2404 return convertToXURI(i_pNode);
2408 uno::Reference<rdf::XNode>
2409 librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const
2411 if (!i_pNode) return nullptr;
2412 if (!librdf_node_is_literal(i_pNode)) {
2413 return convertToXResource(i_pNode);
2415 const unsigned char* value( librdf_node_get_literal_value(i_pNode) );
2416 if (!value) {
2417 throw uno::RuntimeException(
2418 "librdf_TypeConverter::convertToXNode: "
2419 "literal has no value", m_rRep);
2421 const char * lang( librdf_node_get_literal_value_language(i_pNode) );
2422 librdf_uri* pType(
2423 librdf_node_get_literal_value_datatype_uri(i_pNode) );
2424 OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal");
2425 const OUString valueU( OStringToOUString(
2426 std::string_view(reinterpret_cast<const char*>(value)),
2427 RTL_TEXTENCODING_UTF8) );
2428 if (lang) {
2429 const OUString langU( OStringToOUString(
2430 std::string_view(lang),
2431 RTL_TEXTENCODING_UTF8) );
2432 return rdf::Literal::createWithLanguage(m_xContext, valueU, langU);
2433 } else if (pType) {
2434 uno::Reference<rdf::XURI> xType(convertToXURI(pType));
2435 OSL_ENSURE(xType.is(), "convertToXNode: null uri");
2436 return rdf::Literal::createWithType(m_xContext, valueU, xType);
2437 } else {
2438 return rdf::Literal::create(m_xContext, valueU);
2442 rdf::Statement
2443 librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt,
2444 librdf_node* i_pContext) const
2446 if (!i_pStmt) {
2447 throw uno::RuntimeException();
2449 return rdf::Statement(
2450 convertToXResource(librdf_statement_get_subject(i_pStmt)),
2451 convertToXURI(librdf_statement_get_predicate(i_pStmt)),
2452 convertToXNode(librdf_statement_get_object(i_pStmt)),
2453 convertToXURI(i_pContext));
2456 } // closing anonymous implementation namespace
2459 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2460 unoxml_rdfRepository_get_implementation(
2461 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
2463 return cppu::acquire(new librdf_Repository(context));
2466 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */