tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / unoxml / source / rdf / librdf_repository.cxx
blob09b4a9cac17a4178bfcd045a0adb5510024975e4
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 <unotools/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 u"librdf_GraphResult::nextElement: "
514 "librdf_stream_get_object failed"_ustr, *this);
515 throw lang::WrappedTargetException(
516 u"librdf_GraphResult::nextElement: "
517 "librdf_stream_get_object failed"_ustr, *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 u"librdf_QuerySelectResult::nextElement: "
666 "librdf_query_results_get_bindings failed"_ustr, *this);
667 throw lang::WrappedTargetException(
668 u"librdf_QuerySelectResult::nextElement: "
669 "librdf_query_results_get_bindings failed"_ustr, *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_xName(std::move(i_xName))
702 { };
704 // css::rdf::XNode:
705 virtual OUString SAL_CALL getStringValue() override;
707 // css::rdf::XURI:
708 virtual OUString SAL_CALL getNamespace() override;
709 virtual OUString SAL_CALL getLocalName() override;
711 // css::rdf::XNamedGraph:
712 virtual uno::Reference<rdf::XURI> SAL_CALL getName() override;
713 virtual void SAL_CALL clear() override;
714 virtual void SAL_CALL addStatement(
715 const uno::Reference< rdf::XResource > & i_xSubject,
716 const uno::Reference< rdf::XURI > & i_xPredicate,
717 const uno::Reference< rdf::XNode > & i_xObject) override;
718 virtual void SAL_CALL removeStatements(
719 const uno::Reference< rdf::XResource > & i_xSubject,
720 const uno::Reference< rdf::XURI > & i_xPredicate,
721 const uno::Reference< rdf::XNode > & i_xObject) override;
722 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
723 const uno::Reference< rdf::XResource > & i_xSubject,
724 const uno::Reference< rdf::XURI > & i_xPredicate,
725 const uno::Reference< rdf::XNode > & i_xObject) override;
727 private:
729 librdf_NamedGraph(librdf_NamedGraph const&) = delete;
730 librdf_NamedGraph& operator=(librdf_NamedGraph const&) = delete;
732 static OUString createCacheKey_NoLock(
733 const uno::Reference< rdf::XResource > & i_xSubject,
734 const uno::Reference< rdf::XURI > & i_xPredicate,
735 const uno::Reference< rdf::XNode > & i_xObject);
737 /// weak reference: this is needed to check if m_pRep is valid
738 unotools::WeakReference< librdf_Repository > const m_wRep;
739 uno::Reference< rdf::XURI > const m_xName;
741 /// Querying is rather slow, so cache the results.
742 std::map<OUString, std::vector<rdf::Statement>> m_aStatementsCache;
743 std::mutex m_CacheMutex;
747 // css::rdf::XNode:
748 OUString SAL_CALL librdf_NamedGraph::getStringValue()
750 return m_xName->getStringValue();
753 // css::rdf::XURI:
754 OUString SAL_CALL librdf_NamedGraph::getNamespace()
756 return m_xName->getNamespace();
759 OUString SAL_CALL librdf_NamedGraph::getLocalName()
761 return m_xName->getLocalName();
764 // css::rdf::XNamedGraph:
765 uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName()
767 return m_xName;
770 void SAL_CALL librdf_NamedGraph::clear()
772 rtl::Reference< librdf_Repository > xRep( m_wRep );
773 if (!xRep.is()) {
774 throw rdf::RepositoryException(
775 u"librdf_NamedGraph::clear: repository is gone"_ustr, *this);
777 const OUString contextU( m_xName->getStringValue() );
778 try {
779 xRep->clearGraph_NoLock(contextU);
780 } catch (lang::IllegalArgumentException & ex) {
781 css::uno::Any anyEx = cppu::getCaughtException();
782 throw lang::WrappedTargetRuntimeException( ex.Message,
783 *this, anyEx );
785 std::unique_lock g(m_CacheMutex);
786 m_aStatementsCache.clear();
789 void SAL_CALL librdf_NamedGraph::addStatement(
790 const uno::Reference< rdf::XResource > & i_xSubject,
791 const uno::Reference< rdf::XURI > & i_xPredicate,
792 const uno::Reference< rdf::XNode > & i_xObject)
794 rtl::Reference< librdf_Repository > xRep( m_wRep );
795 if (!xRep.is()) {
796 throw rdf::RepositoryException(
797 u"librdf_NamedGraph::addStatement: repository is gone"_ustr, *this);
800 std::unique_lock g(m_CacheMutex);
801 m_aStatementsCache.clear();
803 xRep->addStatementGraph_NoLock(
804 i_xSubject, i_xPredicate, i_xObject, m_xName);
807 void SAL_CALL librdf_NamedGraph::removeStatements(
808 const uno::Reference< rdf::XResource > & i_xSubject,
809 const uno::Reference< rdf::XURI > & i_xPredicate,
810 const uno::Reference< rdf::XNode > & i_xObject)
812 rtl::Reference< librdf_Repository > xRep( m_wRep );
813 if (!xRep.is()) {
814 throw rdf::RepositoryException(
815 u"librdf_NamedGraph::removeStatements: repository is gone"_ustr, *this);
818 std::unique_lock g(m_CacheMutex);
819 m_aStatementsCache.clear();
821 xRep->removeStatementsGraph_NoLock(
822 i_xSubject, i_xPredicate, i_xObject, m_xName);
825 OUString librdf_NamedGraph::createCacheKey_NoLock(
826 const uno::Reference< rdf::XResource > & i_xSubject,
827 const uno::Reference< rdf::XURI > & i_xPredicate,
828 const uno::Reference< rdf::XNode > & i_xObject)
830 OUStringBuffer cacheKey(256);
831 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xSubject, cacheKey);
832 cacheKey.append("\t");
833 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xPredicate, cacheKey);
834 cacheKey.append("\t");
835 librdf_TypeConverter::extractNodeToCacheKey_NoLock(i_xObject, cacheKey);
836 return cacheKey.makeStringAndClear();
839 uno::Reference< container::XEnumeration > SAL_CALL
840 librdf_NamedGraph::getStatements(
841 const uno::Reference< rdf::XResource > & i_xSubject,
842 const uno::Reference< rdf::XURI > & i_xPredicate,
843 const uno::Reference< rdf::XNode > & i_xObject)
845 OUString cacheKey = createCacheKey_NoLock(i_xSubject, i_xPredicate, i_xObject);
847 std::unique_lock g(m_CacheMutex);
848 auto it = m_aStatementsCache.find(cacheKey);
849 if (it != m_aStatementsCache.end()) {
850 return new librdf_GraphResult2(it->second);
854 rtl::Reference< librdf_Repository > xRep( m_wRep );
855 if (!xRep.is()) {
856 throw rdf::RepositoryException(
857 u"librdf_NamedGraph::getStatements: repository is gone"_ustr, *this);
859 std::vector<rdf::Statement> vStatements = xRep->getStatementsGraph_NoLock(
860 i_xSubject, i_xPredicate, i_xObject, m_xName);
863 std::unique_lock g(m_CacheMutex);
864 m_aStatementsCache.emplace(cacheKey, vStatements);
866 return new librdf_GraphResult2(std::move(vStatements));
870 std::shared_ptr<librdf_world> librdf_Repository::m_pWorld;
871 sal_uInt32 librdf_Repository::m_NumInstances = 0;
872 std::mutex librdf_Repository::m_aMutex;
874 librdf_Repository::librdf_Repository(
875 uno::Reference< uno::XComponentContext > const & i_xContext)
876 : /*BaseMutex(),*/ m_xContext(i_xContext)
877 // m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ),
878 , m_pStorage(static_cast<librdf_storage*>(nullptr), safe_librdf_free_storage)
879 , m_pModel (static_cast<librdf_model *>(nullptr), safe_librdf_free_model )
880 , m_TypeConverter(i_xContext, *this)
882 OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context");
884 std::scoped_lock g(m_aMutex);
885 if (!m_NumInstances++) {
886 m_pWorld.reset(m_TypeConverter.createWorld_Lock(),
887 safe_librdf_free_world);
891 librdf_Repository::~librdf_Repository()
893 std::scoped_lock g(m_aMutex);
895 // must destroy these before world!
896 m_pModel.reset();
897 m_pStorage.reset();
899 // FIXME: so it turns out that calling librdf_free_world will
900 // (via raptor_sax2_finish) call xmlCleanupParser, which will
901 // free libxml2's globals! ARRRGH!!! => never call librdf_free_world
902 #if 0
903 if (!--m_NumInstances) {
904 m_pWorld.reset();
906 #endif
909 // com.sun.star.uno.XServiceInfo:
910 OUString SAL_CALL librdf_Repository::getImplementationName()
912 return u"librdf_Repository"_ustr;
915 sal_Bool SAL_CALL librdf_Repository::supportsService(
916 OUString const & serviceName)
918 return cppu::supportsService(this, serviceName);
921 uno::Sequence< OUString > SAL_CALL
922 librdf_Repository::getSupportedServiceNames()
924 return { u"com.sun.star.rdf.Repository"_ustr };
927 // css::rdf::XRepository:
928 uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode()
930 std::scoped_lock g(m_aMutex);
931 const std::shared_ptr<librdf_node> pNode(
932 librdf_new_node_from_blank_identifier(m_pWorld.get(), nullptr),
933 safe_librdf_free_node);
934 if (!pNode) {
935 throw uno::RuntimeException(
936 u"librdf_Repository::createBlankNode: "
937 "librdf_new_node_from_blank_identifier failed"_ustr, *this);
939 const unsigned char * id (librdf_node_get_blank_identifier(pNode.get()));
940 if (!id) {
941 throw uno::RuntimeException(
942 u"librdf_Repository::createBlankNode: "
943 "librdf_node_get_blank_identifier failed"_ustr, *this);
945 const OUString nodeID(OUString::createFromAscii(
946 reinterpret_cast<const char *>(id)));
947 try {
948 return rdf::BlankNode::create(m_xContext, nodeID);
949 } catch (const lang::IllegalArgumentException &) {
950 css::uno::Any anyEx = cppu::getCaughtException();
951 throw lang::WrappedTargetRuntimeException(
952 u"librdf_Repository::createBlankNode: "
953 "illegal blank node label"_ustr, *this, anyEx);
957 //void SAL_CALL
958 uno::Reference<rdf::XNamedGraph> SAL_CALL
959 librdf_Repository::importGraph(::sal_Int16 i_Format,
960 const uno::Reference< io::XInputStream > & i_xInStream,
961 const uno::Reference< rdf::XURI > & i_xGraphName,
962 const uno::Reference< rdf::XURI > & i_xBaseURI)
964 if (!i_xInStream.is()) {
965 throw lang::IllegalArgumentException(
966 u"librdf_Repository::importGraph: stream is null"_ustr, *this, 1);
968 //FIXME: other formats
969 if (i_Format != rdf::FileFormat::RDF_XML) {
970 throw datatransfer::UnsupportedFlavorException(
971 u"librdf_Repository::importGraph: file format not supported"_ustr, *this);
973 if (!i_xGraphName.is()) {
974 throw lang::IllegalArgumentException(
975 u"librdf_Repository::importGraph: graph name is null"_ustr, *this, 2);
977 if (i_xGraphName->getStringValue().startsWith(s_nsOOo))
979 throw lang::IllegalArgumentException(
980 u"librdf_Repository::importGraph: URI is reserved"_ustr, *this, 0);
982 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
983 throw lang::IllegalArgumentException(
984 u"librdf_Repository::importGraph: base URI is null"_ustr, *this, 3);
986 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
987 const OUString baseURIU( i_xBaseURI->getStringValue() );
988 if (baseURIU.indexOf('#') >= 0) {
989 throw lang::IllegalArgumentException(
990 u"librdf_Repository::importGraph: base URI is not absolute"_ustr, *this, 3);
993 const OUString contextU( i_xGraphName->getStringValue() );
995 uno::Sequence<sal_Int8> buf;
996 uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
997 // UGLY: if only redland could read streams...
998 const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
999 // exceptions are propagated
1000 i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
1002 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1004 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1005 throw container::ElementExistException(
1006 u"librdf_Repository::importGraph: graph with given URI exists"_ustr, *this);
1008 const OString context(
1009 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1011 const std::shared_ptr<librdf_node> pContext(
1012 librdf_new_node_from_uri_string(m_pWorld.get(),
1013 reinterpret_cast<const unsigned char*> (context.getStr())),
1014 safe_librdf_free_node);
1015 if (!pContext) {
1016 throw uno::RuntimeException(
1017 u"librdf_Repository::importGraph: librdf_new_node_from_uri_string failed"_ustr, *this);
1020 const OString baseURI(
1021 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1022 const std::shared_ptr<librdf_uri> pBaseURI(
1023 librdf_new_uri(m_pWorld.get(),
1024 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1025 safe_librdf_free_uri);
1026 if (!pBaseURI) {
1027 throw uno::RuntimeException( u"librdf_Repository::importGraph: librdf_new_uri failed"_ustr, *this);
1030 const std::shared_ptr<librdf_parser> pParser(
1031 librdf_new_parser(m_pWorld.get(), "rdfxml", nullptr, nullptr),
1032 safe_librdf_free_parser);
1033 if (!pParser) {
1034 throw uno::RuntimeException(
1035 u"librdf_Repository::importGraph: "
1036 "librdf_new_parser failed"_ustr, *this);
1039 const std::shared_ptr<librdf_stream> pStream(
1040 librdf_parser_parse_counted_string_as_stream(pParser.get(),
1041 reinterpret_cast<const unsigned char*>(buf.getConstArray()),
1042 buf.getLength(), pBaseURI.get()),
1043 safe_librdf_free_stream);
1044 if (!pStream) {
1045 throw rdf::ParseException(
1046 u"librdf_Repository::importGraph: "
1047 "librdf_parser_parse_counted_string_as_stream failed"_ustr, *this);
1049 rtl::Reference<librdf_NamedGraph> const pGraph(
1050 new librdf_NamedGraph(this, i_xGraphName));
1051 m_NamedGraphs.insert(std::make_pair(contextU, pGraph));
1052 if (librdf_model_context_add_statements(m_pModel.get(),
1053 pContext.get(), pStream.get())) {
1054 throw rdf::RepositoryException(
1055 u"librdf_Repository::importGraph: "
1056 "librdf_model_context_add_statements failed"_ustr, *this);
1059 return pGraph;
1062 void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
1064 if (!length)
1065 return;
1067 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream,
1068 uno::UNO_QUERY);
1070 bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData();
1072 // exceptions are propagated
1073 if (!bAddChaff)
1075 const uno::Sequence<sal_Int8> buf(
1076 reinterpret_cast<sal_Int8*>(pBuffer), length);
1077 rStream->writeBytes(buf);
1079 else
1081 unsigned char *postcomment =
1082 reinterpret_cast<unsigned char*>(strchr(reinterpret_cast<char*>(pBuffer), '\n'));
1083 if (postcomment != nullptr)
1085 ++postcomment;
1087 size_t preamblelen = postcomment - pBuffer;
1089 uno::Sequence<sal_Int8> buf(
1090 reinterpret_cast<sal_Int8*>(pBuffer), preamblelen);
1091 rStream->writeBytes(buf);
1093 OString aComment =
1094 "<!--" +
1095 comphelper::xml::makeXMLChaff() +
1096 "-->";
1098 buf = uno::Sequence<sal_Int8>(
1099 reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength());
1100 rStream->writeBytes(buf);
1102 buf = uno::Sequence<sal_Int8>(
1103 reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen);
1104 rStream->writeBytes(buf);
1109 void SAL_CALL
1110 librdf_Repository::exportGraph(::sal_Int16 i_Format,
1111 const uno::Reference< io::XOutputStream > & i_xOutStream,
1112 const uno::Reference< rdf::XURI > & i_xGraphName,
1113 const uno::Reference< rdf::XURI > & i_xBaseURI)
1115 if (!i_xOutStream.is()) {
1116 throw lang::IllegalArgumentException(
1117 u"librdf_Repository::exportGraph: stream is null"_ustr, *this, 1);
1119 // FIXME: other formats
1120 if (i_Format != rdf::FileFormat::RDF_XML) {
1121 throw datatransfer::UnsupportedFlavorException(
1122 u"librdf_Repository::exportGraph: "
1123 "file format not supported"_ustr, *this);
1125 if (!i_xGraphName.is()) {
1126 throw lang::IllegalArgumentException(
1127 u"librdf_Repository::exportGraph: "
1128 "graph name is null"_ustr, *this, 2);
1130 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
1131 throw lang::IllegalArgumentException(
1132 u"librdf_Repository::exportGraph: "
1133 "base URI is null"_ustr, *this, 3);
1135 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
1136 const OUString baseURIU( i_xBaseURI->getStringValue() );
1137 if (baseURIU.indexOf('#') >= 0) {
1138 throw lang::IllegalArgumentException(
1139 u"librdf_Repository::exportGraph: "
1140 "base URI is not absolute"_ustr, *this, 3);
1143 const OUString contextU( i_xGraphName->getStringValue() );
1145 std::unique_lock g(m_aMutex); // don't call i_x* with mutex locked
1147 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1148 throw container::NoSuchElementException(
1149 u"librdf_Repository::exportGraph: "
1150 "no graph with given URI exists"_ustr, *this);
1152 const OString context(
1153 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1155 const std::shared_ptr<librdf_node> pContext(
1156 librdf_new_node_from_uri_string(m_pWorld.get(),
1157 reinterpret_cast<const unsigned char*> (context.getStr())),
1158 safe_librdf_free_node);
1159 if (!pContext) {
1160 throw uno::RuntimeException(
1161 u"librdf_Repository::exportGraph: "
1162 "librdf_new_node_from_uri_string failed"_ustr, *this);
1164 const OString baseURI(
1165 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1166 const std::shared_ptr<librdf_uri> pBaseURI(
1167 librdf_new_uri(m_pWorld.get(),
1168 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1169 safe_librdf_free_uri);
1170 if (!pBaseURI) {
1171 throw uno::RuntimeException(
1172 u"librdf_Repository::exportGraph: "
1173 "librdf_new_uri failed"_ustr, *this);
1176 const std::shared_ptr<librdf_stream> pStream(
1177 librdf_model_context_as_stream(m_pModel.get(), pContext.get()),
1178 safe_librdf_free_stream);
1179 if (!pStream) {
1180 throw rdf::RepositoryException(
1181 u"librdf_Repository::exportGraph: "
1182 "librdf_model_context_as_stream failed"_ustr, *this);
1184 const char * const format("rdfxml");
1185 // #i116443#: abbrev breaks when certain URIs are used as data types
1186 // const char *format("rdfxml-abbrev");
1187 const std::shared_ptr<librdf_serializer> pSerializer(
1188 librdf_new_serializer(m_pWorld.get(), format, nullptr, nullptr),
1189 safe_librdf_free_serializer);
1190 if (!pSerializer) {
1191 throw uno::RuntimeException(
1192 u"librdf_Repository::exportGraph: "
1193 "librdf_new_serializer failed"_ustr, *this);
1196 const std::shared_ptr<librdf_uri> pRelativeURI(
1197 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1198 ("http://feature.librdf.org/raptor-relativeURIs")),
1199 safe_librdf_free_uri);
1200 const std::shared_ptr<librdf_uri> pWriteBaseURI(
1201 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1202 ("http://feature.librdf.org/raptor-writeBaseURI")),
1203 safe_librdf_free_uri);
1204 const std::shared_ptr<librdf_node> p0(
1205 librdf_new_node_from_literal(m_pWorld.get(),
1206 reinterpret_cast<const unsigned char*> ("0"), nullptr, 0),
1207 safe_librdf_free_node);
1208 const std::shared_ptr<librdf_node> p1(
1209 librdf_new_node_from_literal(m_pWorld.get(),
1210 reinterpret_cast<const unsigned char*> ("1"), nullptr, 0),
1211 safe_librdf_free_node);
1212 if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) {
1213 throw uno::RuntimeException(
1214 u"librdf_Repository::exportGraph: "
1215 "librdf_new_uri or librdf_new_node_from_literal failed"_ustr, *this);
1218 // make URIs relative to base URI
1219 if (librdf_serializer_set_feature(pSerializer.get(),
1220 pRelativeURI.get(), p1.get()))
1222 throw uno::RuntimeException(
1223 u"librdf_Repository::exportGraph: "
1224 "librdf_serializer_set_feature relativeURIs failed"_ustr, *this);
1226 // but do not write the base URI to the file!
1227 if (librdf_serializer_set_feature(pSerializer.get(),
1228 pWriteBaseURI.get(), p0.get()))
1230 throw uno::RuntimeException(
1231 u"librdf_Repository::exportGraph: "
1232 "librdf_serializer_set_feature writeBaseURI failed"_ustr, *this);
1235 size_t length;
1236 const std::shared_ptr<unsigned char> pBuf(
1237 librdf_serializer_serialize_stream_to_counted_string(
1238 pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free);
1239 if (!pBuf) {
1240 throw rdf::RepositoryException(
1241 u"librdf_Repository::exportGraph: "
1242 "librdf_serializer_serialize_stream_to_counted_string failed"_ustr,
1243 *this);
1246 g.unlock(); // release Mutex before calling i_xOutStream methods
1248 addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
1251 uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
1252 librdf_Repository::getGraphNames()
1254 std::scoped_lock g(m_aMutex);
1255 ::std::vector< uno::Reference<rdf::XURI> > ret;
1256 std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(),
1257 std::back_inserter(ret),
1258 [](std::pair<OUString, ::rtl::Reference<librdf_NamedGraph>> const& it)
1259 { return it.second->getName(); });
1260 return comphelper::containerToSequence(ret);
1263 uno::Reference< rdf::XNamedGraph > SAL_CALL
1264 librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1266 if (!i_xGraphName.is()) {
1267 throw lang::IllegalArgumentException(
1268 u"librdf_Repository::getGraph: URI is null"_ustr, *this, 0);
1270 const OUString contextU( i_xGraphName->getStringValue() );
1272 std::scoped_lock g(m_aMutex);
1273 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
1274 if (iter != m_NamedGraphs.end()) {
1275 return iter->second;
1276 } else {
1277 return nullptr;
1281 uno::Reference< rdf::XNamedGraph > SAL_CALL
1282 librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1284 if (!i_xGraphName.is()) {
1285 throw lang::IllegalArgumentException(
1286 u"librdf_Repository::createGraph: URI is null"_ustr, *this, 0);
1289 const OUString contextU( i_xGraphName->getStringValue() );
1290 if (contextU.startsWith(s_nsOOo))
1292 throw lang::IllegalArgumentException(
1293 u"librdf_Repository::createGraph: URI is reserved"_ustr, *this, 0);
1296 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1298 // NB: librdf does not have a concept of graphs as such;
1299 // a librdf named graph exists iff the model contains a statement with
1300 // the graph name as context
1302 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1303 throw container::ElementExistException(
1304 u"librdf_Repository::createGraph: graph with given URI exists"_ustr, *this);
1306 m_NamedGraphs.insert(std::make_pair(contextU,
1307 new librdf_NamedGraph(this, i_xGraphName)));
1308 return m_NamedGraphs.find(contextU)->second;
1311 void SAL_CALL
1312 librdf_Repository::destroyGraph(
1313 const uno::Reference< rdf::XURI > & i_xGraphName)
1315 if (!i_xGraphName.is()) {
1316 throw lang::IllegalArgumentException(
1317 u"librdf_Repository::destroyGraph: URI is null"_ustr, *this, 0);
1319 const OUString contextU( i_xGraphName->getStringValue() );
1321 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1323 const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) );
1324 m_NamedGraphs.erase(iter);
1327 bool isMetadatableWithoutMetadata(
1328 uno::Reference<uno::XInterface> const & i_xNode)
1330 const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY );
1331 return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty());
1334 uno::Reference< container::XEnumeration > SAL_CALL
1335 librdf_Repository::getStatements(
1336 const uno::Reference< rdf::XResource > & i_xSubject,
1337 const uno::Reference< rdf::XURI > & i_xPredicate,
1338 const uno::Reference< rdf::XNode > & i_xObject)
1340 if (isMetadatableWithoutMetadata(i_xSubject) ||
1341 isMetadatableWithoutMetadata(i_xPredicate) ||
1342 isMetadatableWithoutMetadata(i_xObject))
1344 return new librdf_GraphResult(this, m_aMutex,
1345 std::shared_ptr<librdf_stream>(),
1346 std::shared_ptr<librdf_node>());
1349 librdf_TypeConverter::Statement const stmt(
1350 librdf_TypeConverter::extractStatement_NoLock(
1351 i_xSubject, i_xPredicate, i_xObject));
1353 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1355 const std::shared_ptr<librdf_statement> pStatement(
1356 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1357 safe_librdf_free_statement);
1358 OSL_ENSURE(pStatement, "mkStatement failed");
1360 const std::shared_ptr<librdf_stream> pStream(
1361 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1362 safe_librdf_free_stream);
1363 if (!pStream) {
1364 throw rdf::RepositoryException(
1365 u"librdf_Repository::getStatements: "
1366 "librdf_model_find_statements failed"_ustr, *this);
1369 return new librdf_GraphResult(this, m_aMutex, pStream,
1370 std::shared_ptr<librdf_node>());
1374 uno::Reference< rdf::XQuerySelectResult > SAL_CALL
1375 librdf_Repository::querySelect(const OUString & i_rQuery)
1377 std::scoped_lock g(m_aMutex);
1378 const OString query(
1379 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1380 const std::shared_ptr<librdf_query> pQuery(
1381 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1382 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1383 safe_librdf_free_query);
1384 if (!pQuery) {
1385 throw rdf::QueryException(
1386 u"librdf_Repository::querySelect: "
1387 "librdf_new_query failed"_ustr, *this);
1389 const std::shared_ptr<librdf_query_results> pResults(
1390 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1391 safe_librdf_free_query_results);
1392 if (!pResults || !librdf_query_results_is_bindings(pResults.get())) {
1393 throw rdf::QueryException(
1394 u"librdf_Repository::querySelect: "
1395 "query result is null or not bindings"_ustr, *this);
1398 const int count( librdf_query_results_get_bindings_count(pResults.get()) );
1399 if (count < 0) {
1400 throw rdf::QueryException(
1401 u"librdf_Repository::querySelect: "
1402 "librdf_query_results_get_bindings_count failed"_ustr, *this);
1404 uno::Sequence< OUString > names(count);
1405 auto namesRange = asNonConstRange(names);
1406 for (int i = 0; i < count; ++i) {
1407 const char* name( librdf_query_results_get_binding_name(
1408 pResults.get(), i) );
1409 if (!name) {
1410 throw rdf::QueryException(
1411 u"librdf_Repository::querySelect: binding is null"_ustr, *this);
1414 namesRange[i] = OUString::createFromAscii(name);
1417 return new librdf_QuerySelectResult(this, m_aMutex,
1418 pQuery, pResults, names);
1421 uno::Reference< container::XEnumeration > SAL_CALL
1422 librdf_Repository::queryConstruct(const OUString & i_rQuery)
1424 std::scoped_lock g(m_aMutex);
1425 const OString query(
1426 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1427 const std::shared_ptr<librdf_query> pQuery(
1428 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1429 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1430 safe_librdf_free_query);
1431 if (!pQuery) {
1432 throw rdf::QueryException(
1433 u"librdf_Repository::queryConstruct: "
1434 "librdf_new_query failed"_ustr, *this);
1436 const std::shared_ptr<librdf_query_results> pResults(
1437 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1438 safe_librdf_free_query_results);
1439 if (!pResults || !librdf_query_results_is_graph(pResults.get())) {
1440 throw rdf::QueryException(
1441 u"librdf_Repository::queryConstruct: "
1442 "query result is null or not graph"_ustr, *this);
1444 const std::shared_ptr<librdf_stream> pStream(
1445 librdf_query_results_as_stream(pResults.get()),
1446 safe_librdf_free_stream);
1447 if (!pStream) {
1448 throw rdf::QueryException(
1449 u"librdf_Repository::queryConstruct: "
1450 "librdf_query_results_as_stream failed"_ustr, *this);
1453 return new librdf_GraphResult(this, m_aMutex, pStream,
1454 std::shared_ptr<librdf_node>(), pQuery);
1457 sal_Bool SAL_CALL
1458 librdf_Repository::queryAsk(const OUString & i_rQuery)
1460 std::scoped_lock g(m_aMutex);
1462 const OString query(
1463 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1464 const std::shared_ptr<librdf_query> pQuery(
1465 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1466 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1467 safe_librdf_free_query);
1468 if (!pQuery) {
1469 throw rdf::QueryException(
1470 u"librdf_Repository::queryAsk: "
1471 "librdf_new_query failed"_ustr, *this);
1473 const std::shared_ptr<librdf_query_results> pResults(
1474 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1475 safe_librdf_free_query_results);
1476 if (!pResults || !librdf_query_results_is_boolean(pResults.get())) {
1477 throw rdf::QueryException(
1478 u"librdf_Repository::queryAsk: "
1479 "query result is null or not boolean"_ustr, *this);
1481 return bool(librdf_query_results_get_boolean(pResults.get()));
1484 // css::rdf::XDocumentRepository:
1485 void SAL_CALL librdf_Repository::setStatementRDFa(
1486 const uno::Reference< rdf::XResource > & i_xSubject,
1487 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
1488 const uno::Reference< rdf::XMetadatable > & i_xObject,
1489 const OUString & i_rRDFaContent,
1490 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
1492 if (!i_xSubject.is()) {
1493 throw lang::IllegalArgumentException(
1494 u"librdf_Repository::setStatementRDFa: Subject is null"_ustr, *this, 0);
1496 if (!i_rPredicates.hasElements()) {
1497 throw lang::IllegalArgumentException(
1498 u"librdf_Repository::setStatementRDFa: no Predicates"_ustr,
1499 *this, 1);
1501 if (std::any_of(i_rPredicates.begin(), i_rPredicates.end(),
1502 [](const uno::Reference< rdf::XURI >& rPredicate) { return !rPredicate.is(); })) {
1503 throw lang::IllegalArgumentException(
1504 u"librdf_Repository::setStatementRDFa: Predicate is null"_ustr, *this, 1);
1506 if (!i_xObject.is()) {
1507 throw lang::IllegalArgumentException(
1508 u"librdf_Repository::setStatementRDFa: Object is null"_ustr, *this, 2);
1510 const uno::Reference<lang::XServiceInfo> xService(i_xObject,
1511 uno::UNO_QUERY_THROW);
1512 uno::Reference<text::XTextRange> xTextRange;
1513 if (xService->supportsService(u"com.sun.star.table.Cell"_ustr) ||
1514 xService->supportsService(u"com.sun.star.text.CellProperties"_ustr) || // for writer
1515 xService->supportsService(u"com.sun.star.text.Paragraph"_ustr))
1517 xTextRange.set(i_xObject, uno::UNO_QUERY_THROW);
1519 else if (xService->supportsService(u"com.sun.star.text.Bookmark"_ustr) ||
1520 xService->supportsService(u"com.sun.star.text.InContentMetadata"_ustr))
1522 const uno::Reference<text::XTextContent> xTextContent(i_xObject,
1523 uno::UNO_QUERY_THROW);
1524 xTextRange = xTextContent->getAnchor();
1526 if (!xTextRange.is()) {
1527 throw lang::IllegalArgumentException(
1528 u"librdf_Repository::setStatementRDFa: "
1529 "Object does not support RDFa"_ustr, *this, 2);
1531 // ensure that the metadatable has an XML ID
1532 i_xObject->ensureMetadataReference();
1533 const beans::StringPair mdref( i_xObject->getMetadataReference() );
1534 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1535 throw uno::RuntimeException(
1536 u"librdf_Repository::setStatementRDFa: "
1537 "ensureMetadataReference did not"_ustr, *this);
1539 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1540 OUString const sContext(s_nsOOo + sXmlId);
1541 OUString const content( (i_rRDFaContent.isEmpty())
1542 ? xTextRange->getString()
1543 : i_rRDFaContent );
1544 uno::Reference<rdf::XNode> xContent;
1545 try {
1546 if (i_xRDFaDatatype.is()) {
1547 xContent.set(rdf::Literal::createWithType(m_xContext,
1548 content, i_xRDFaDatatype),
1549 uno::UNO_QUERY_THROW);
1550 } else {
1551 xContent.set(rdf::Literal::create(m_xContext, content),
1552 uno::UNO_QUERY_THROW);
1554 } catch (const lang::IllegalArgumentException &) {
1555 css::uno::Any anyEx = cppu::getCaughtException();
1556 throw lang::WrappedTargetRuntimeException(
1557 u"librdf_Repository::setStatementRDFa: "
1558 "cannot create literal"_ustr, *this, anyEx);
1561 std::shared_ptr<librdf_TypeConverter::Resource> const pSubject(
1562 librdf_TypeConverter::extractResource_NoLock(i_xSubject));
1563 std::shared_ptr<librdf_TypeConverter::Node> const pContent(
1564 librdf_TypeConverter::extractNode_NoLock(xContent));
1565 ::std::vector< std::shared_ptr<librdf_TypeConverter::Resource> >
1566 predicates;
1567 ::std::transform(i_rPredicates.begin(), i_rPredicates.end(),
1568 ::std::back_inserter(predicates),
1569 [](uno::Reference<rdf::XURI> const& xURI)
1570 { return librdf_TypeConverter::extractResource_NoLock(xURI); });
1572 removeStatementRDFa(i_xObject); // not atomic with insertion?
1574 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1576 if (i_rRDFaContent.isEmpty()) {
1577 m_RDFaXHTMLContentSet.erase(sXmlId);
1578 } else {
1579 m_RDFaXHTMLContentSet.insert(sXmlId);
1583 for (const auto& rPredicatePtr : predicates)
1585 addStatementGraph_Lock(
1586 librdf_TypeConverter::Statement(pSubject,
1587 std::dynamic_pointer_cast<librdf_TypeConverter::URI>(rPredicatePtr),
1588 pContent),
1589 sContext, true);
1592 catch (const container::NoSuchElementException&)
1594 css::uno::Any anyEx = cppu::getCaughtException();
1595 throw lang::WrappedTargetRuntimeException(
1596 u"librdf_Repository::setStatementRDFa: "
1597 "cannot addStatementGraph"_ustr, *this, anyEx);
1601 void SAL_CALL librdf_Repository::removeStatementRDFa(
1602 const uno::Reference< rdf::XMetadatable > & i_xElement)
1604 if (!i_xElement.is()) {
1605 throw lang::IllegalArgumentException(
1606 u"librdf_Repository::removeStatementRDFa: Element is null"_ustr,
1607 *this, 0);
1610 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1611 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1612 return; // nothing to do...
1615 OUString const sXmlId(s_nsOOo + mdref.First + "#" + mdref.Second);
1617 clearGraph_NoLock(sXmlId, true);
1620 beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
1621 librdf_Repository::getStatementRDFa(
1622 const uno::Reference< rdf::XMetadatable > & i_xElement)
1624 if (!i_xElement.is()) {
1625 throw lang::IllegalArgumentException(
1626 u"librdf_Repository::getStatementRDFa: Element is null"_ustr, *this, 0);
1628 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1629 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1630 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >();
1632 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1633 uno::Reference<rdf::XURI> xXmlId;
1634 try {
1635 xXmlId.set( rdf::URI::create(m_xContext, s_nsOOo + sXmlId),
1636 uno::UNO_SET_THROW);
1637 } catch (const lang::IllegalArgumentException &) {
1638 css::uno::Any anyEx = cppu::getCaughtException();
1639 throw lang::WrappedTargetRuntimeException(
1640 u"librdf_Repository::getStatementRDFa: "
1641 "cannot create URI for XML ID"_ustr, *this, anyEx);
1644 ::std::vector< rdf::Statement > ret;
1647 ret = getStatementsGraph_NoLock(nullptr, nullptr, nullptr, xXmlId, true);
1649 catch (const container::NoSuchElementException&)
1651 css::uno::Any anyEx = cppu::getCaughtException();
1652 throw lang::WrappedTargetRuntimeException(
1653 u"librdf_Repository::getStatementRDFa: "
1654 "cannot getStatementsGraph"_ustr, *this, anyEx);
1657 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1659 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
1660 comphelper::containerToSequence(ret), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
1663 extern "C"
1664 librdf_statement *rdfa_context_stream_map_handler(
1665 librdf_stream *i_pStream, void *, librdf_statement *i_pStatement)
1667 OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null");
1668 if (i_pStream) {
1669 librdf_node *pCtxt(
1670 #if LIBRDF_VERSION >= 10012
1671 librdf_stream_get_context2(i_pStream) );
1672 #else
1673 static_cast<librdf_node *>(librdf_stream_get_context(i_pStream)) );
1674 #endif
1675 OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null");
1676 if (pCtxt && isInternalContext(pCtxt)) {
1677 return i_pStatement;
1680 return nullptr;
1683 uno::Reference< container::XEnumeration > SAL_CALL
1684 librdf_Repository::getStatementsRDFa(
1685 const uno::Reference< rdf::XResource > & i_xSubject,
1686 const uno::Reference< rdf::XURI > & i_xPredicate,
1687 const uno::Reference< rdf::XNode > & i_xObject)
1689 if (isMetadatableWithoutMetadata(i_xSubject) ||
1690 isMetadatableWithoutMetadata(i_xPredicate) ||
1691 isMetadatableWithoutMetadata(i_xObject))
1693 return new librdf_GraphResult(this, m_aMutex,
1694 std::shared_ptr<librdf_stream>(),
1695 std::shared_ptr<librdf_node>());
1698 librdf_TypeConverter::Statement const stmt(
1699 librdf_TypeConverter::extractStatement_NoLock(
1700 i_xSubject, i_xPredicate, i_xObject));
1702 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1704 const std::shared_ptr<librdf_statement> pStatement(
1705 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1706 safe_librdf_free_statement);
1707 OSL_ENSURE(pStatement, "mkStatement failed");
1709 const std::shared_ptr<librdf_stream> pStream(
1710 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1711 safe_librdf_free_stream);
1712 if (!pStream) {
1713 throw rdf::RepositoryException(
1714 u"librdf_Repository::getStatementsRDFa: "
1715 "librdf_model_find_statements failed"_ustr, *this);
1718 if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler,
1719 nullptr, nullptr)) {
1720 throw rdf::RepositoryException(
1721 u"librdf_Repository::getStatementsRDFa: "
1722 "librdf_stream_add_map failed"_ustr, *this);
1725 return new librdf_GraphResult(this, m_aMutex, pStream,
1726 std::shared_ptr<librdf_node>());
1729 // css::lang::XInitialization:
1730 void SAL_CALL librdf_Repository::initialize(
1731 const uno::Sequence< css::uno::Any > &)
1733 std::scoped_lock g(m_aMutex);
1735 // m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
1736 m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()),
1737 safe_librdf_free_storage);
1738 m_pModel.reset(m_TypeConverter.createModel_Lock(
1739 m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
1742 NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock(
1743 OUString const& i_rGraphName, bool i_Internal)
1744 // throw (uno::RuntimeException, container::NoSuchElementException,
1745 // rdf::RepositoryException)
1747 std::scoped_lock g(m_aMutex);
1749 return clearGraph_Lock(i_rGraphName, i_Internal);
1752 NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock(
1753 OUString const& i_rGraphName, bool i_Internal)
1755 // internal: must be called with mutex locked!
1756 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) );
1757 if (!i_Internal && iter == m_NamedGraphs.end()) {
1758 throw container::NoSuchElementException(
1759 u"librdf_Repository::clearGraph: "
1760 "no graph with given URI exists"_ustr, *this);
1762 const OString context(
1763 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1765 const std::shared_ptr<librdf_node> pContext(
1766 librdf_new_node_from_uri_string(m_pWorld.get(),
1767 reinterpret_cast<const unsigned char*> (context.getStr())),
1768 safe_librdf_free_node);
1769 if (!pContext) {
1770 throw uno::RuntimeException(
1771 u"librdf_Repository::clearGraph: "
1772 "librdf_new_node_from_uri_string failed"_ustr, *this);
1774 if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get()))
1776 throw rdf::RepositoryException(
1777 u"librdf_Repository::clearGraph: "
1778 "librdf_model_context_remove_statements failed"_ustr, *this);
1780 return iter;
1783 void librdf_Repository::addStatementGraph_NoLock(
1784 const uno::Reference< rdf::XResource > & i_xSubject,
1785 const uno::Reference< rdf::XURI > & i_xPredicate,
1786 const uno::Reference< rdf::XNode > & i_xObject,
1787 const uno::Reference< rdf::XURI > & i_xGraphName)
1788 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1789 // container::NoSuchElementException, rdf::RepositoryException)
1791 if (!i_xSubject.is()) {
1792 throw lang::IllegalArgumentException(
1793 u"librdf_Repository::addStatement: Subject is null"_ustr, *this, 0);
1795 if (!i_xPredicate.is()) {
1796 throw lang::IllegalArgumentException(
1797 u"librdf_Repository::addStatement: Predicate is null"_ustr,
1798 *this, 1);
1800 if (!i_xObject.is()) {
1801 throw lang::IllegalArgumentException(
1802 u"librdf_Repository::addStatement: Object is null"_ustr, *this, 2);
1805 librdf_TypeConverter::Statement const stmt(
1806 librdf_TypeConverter::extractStatement_NoLock(
1807 i_xSubject, i_xPredicate, i_xObject));
1809 const OUString contextU( i_xGraphName->getStringValue() );
1811 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1813 addStatementGraph_Lock(stmt, contextU, false/*i_Internal*/);
1816 void librdf_Repository::addStatementGraph_Lock(
1817 librdf_TypeConverter::Statement const& i_rStatement,
1818 OUString const& i_rGraphName,
1819 bool i_Internal)
1821 if (!i_Internal
1822 && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end()))
1824 throw container::NoSuchElementException(
1825 u"librdf_Repository::addStatement: "
1826 "no graph with given URI exists"_ustr, *this);
1828 const OString context(
1829 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1831 const std::shared_ptr<librdf_node> pContext(
1832 librdf_new_node_from_uri_string(m_pWorld.get(),
1833 reinterpret_cast<const unsigned char*> (context.getStr())),
1834 safe_librdf_free_node);
1835 if (!pContext) {
1836 throw uno::RuntimeException(
1837 u"librdf_Repository::addStatement: "
1838 "librdf_new_node_from_uri_string failed"_ustr, *this);
1840 const std::shared_ptr<librdf_statement> pStatement(
1841 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), i_rStatement),
1842 safe_librdf_free_statement);
1843 OSL_ENSURE(pStatement, "mkStatement failed");
1845 // Test for duplicate statement
1846 // librdf_model_add_statement disallows duplicates while
1847 // librdf_model_context_add_statement allows duplicates
1849 const std::shared_ptr<librdf_stream> pStream(
1850 librdf_model_find_statements_in_context(m_pModel.get(),
1851 pStatement.get(), pContext.get()),
1852 safe_librdf_free_stream);
1853 if (pStream && !librdf_stream_end(pStream.get()))
1854 return;
1857 if (librdf_model_context_add_statement(m_pModel.get(),
1858 pContext.get(), pStatement.get())) {
1859 throw rdf::RepositoryException(
1860 u"librdf_Repository::addStatement: "
1861 "librdf_model_context_add_statement failed"_ustr, *this);
1865 void librdf_Repository::removeStatementsGraph_NoLock(
1866 const uno::Reference< rdf::XResource > & i_xSubject,
1867 const uno::Reference< rdf::XURI > & i_xPredicate,
1868 const uno::Reference< rdf::XNode > & i_xObject,
1869 const uno::Reference< rdf::XURI > & i_xGraphName)
1870 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1871 // container::NoSuchElementException, rdf::RepositoryException)
1873 if (isMetadatableWithoutMetadata(i_xSubject) ||
1874 isMetadatableWithoutMetadata(i_xPredicate) ||
1875 isMetadatableWithoutMetadata(i_xObject))
1877 return;
1880 librdf_TypeConverter::Statement const stmt(
1881 librdf_TypeConverter::extractStatement_NoLock(
1882 i_xSubject, i_xPredicate, i_xObject));
1883 const OUString contextU( i_xGraphName->getStringValue() );
1885 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1887 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1888 throw container::NoSuchElementException(
1889 u"librdf_Repository::removeStatements: "
1890 "no graph with given URI exists"_ustr, *this);
1892 const OString context(
1893 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1895 const std::shared_ptr<librdf_node> pContext(
1896 librdf_new_node_from_uri_string(m_pWorld.get(),
1897 reinterpret_cast<const unsigned char*> (context.getStr())),
1898 safe_librdf_free_node);
1899 if (!pContext) {
1900 throw uno::RuntimeException(
1901 u"librdf_Repository::removeStatements: "
1902 "librdf_new_node_from_uri_string failed"_ustr, *this);
1904 const std::shared_ptr<librdf_statement> pStatement(
1905 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1906 safe_librdf_free_statement);
1907 OSL_ENSURE(pStatement, "mkStatement failed");
1909 const std::shared_ptr<librdf_stream> pStream(
1910 librdf_model_find_statements_in_context(m_pModel.get(),
1911 pStatement.get(), pContext.get()),
1912 safe_librdf_free_stream);
1913 if (!pStream) {
1914 throw rdf::RepositoryException(
1915 u"librdf_Repository::removeStatements: "
1916 "librdf_model_find_statements_in_context failed"_ustr, *this);
1919 if (librdf_stream_end(pStream.get()))
1920 return;
1922 do {
1923 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
1924 if (!pStmt) {
1925 throw rdf::RepositoryException(
1926 u"librdf_Repository::removeStatements: "
1927 "librdf_stream_get_object failed"_ustr, *this);
1929 if (librdf_model_context_remove_statement(m_pModel.get(),
1930 pContext.get(), pStmt)) {
1931 throw rdf::RepositoryException(
1932 u"librdf_Repository::removeStatements: "
1933 "librdf_model_context_remove_statement failed"_ustr, *this);
1935 } while (!librdf_stream_next(pStream.get()));
1938 std::vector<rdf::Statement>
1939 librdf_Repository::getStatementsGraph_NoLock(
1940 const uno::Reference< rdf::XResource > & i_xSubject,
1941 const uno::Reference< rdf::XURI > & i_xPredicate,
1942 const uno::Reference< rdf::XNode > & i_xObject,
1943 const uno::Reference< rdf::XURI > & i_xGraphName,
1944 bool i_Internal)
1945 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1946 // container::NoSuchElementException, rdf::RepositoryException)
1948 std::vector<rdf::Statement> ret;
1950 // N.B.: if any of subject, predicate, object is an XMetadatable, and
1951 // has no metadata reference, then there cannot be any node in the graph
1952 // representing it; in order to prevent side effect
1953 // (ensureMetadataReference), check for this condition and return
1954 if (isMetadatableWithoutMetadata(i_xSubject) ||
1955 isMetadatableWithoutMetadata(i_xPredicate) ||
1956 isMetadatableWithoutMetadata(i_xObject))
1958 return ret;
1961 librdf_TypeConverter::Statement const stmt(
1962 librdf_TypeConverter::extractStatement_NoLock(
1963 i_xSubject, i_xPredicate, i_xObject));
1964 const OUString contextU( i_xGraphName->getStringValue() );
1966 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1968 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1969 throw container::NoSuchElementException(
1970 u"librdf_Repository::getStatements: "
1971 "no graph with given URI exists"_ustr, *this);
1973 const OString context(
1974 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1976 const std::shared_ptr<librdf_node> pContext(
1977 librdf_new_node_from_uri_string(m_pWorld.get(),
1978 reinterpret_cast<const unsigned char*> (context.getStr())),
1979 safe_librdf_free_node);
1980 if (!pContext) {
1981 throw uno::RuntimeException(
1982 u"librdf_Repository::getStatements: "
1983 "librdf_new_node_from_uri_string failed"_ustr, *this);
1985 const std::shared_ptr<librdf_statement> pStatement(
1986 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1987 safe_librdf_free_statement);
1988 OSL_ENSURE(pStatement, "mkStatement failed");
1990 const std::shared_ptr<librdf_stream> pStream(
1991 librdf_model_find_statements_in_context(m_pModel.get(),
1992 pStatement.get(), pContext.get()),
1993 safe_librdf_free_stream);
1994 if (!pStream) {
1995 throw rdf::RepositoryException(
1996 u"librdf_Repository::getStatements: "
1997 "librdf_model_find_statements_in_context failed"_ustr, *this);
2000 librdf_node *pCtxt1(
2001 #if LIBRDF_VERSION >= 10012
2002 librdf_stream_get_context2(pStream.get()) );
2003 #else
2004 static_cast<librdf_node *>(librdf_stream_get_context(pStream.get())) );
2005 #endif
2006 while (!librdf_stream_end(pStream.get()))
2008 auto pCtxt = pCtxt1;
2009 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
2010 if (!pStmt) {
2011 rdf::QueryException e(
2012 u"librdf_GraphResult::nextElement: "
2013 "librdf_stream_get_object failed"_ustr, *this);
2014 throw lang::WrappedTargetException(
2015 u"librdf_GraphResult::nextElement: "
2016 "librdf_stream_get_object failed"_ustr, *this,
2017 uno::Any(e));
2019 // NB: pCtxt may be null here if this is result of a graph query
2020 if (pCtxt && isInternalContext(pCtxt)) {
2021 pCtxt = nullptr; // XML ID context is implementation detail!
2024 ret.emplace_back(
2025 getTypeConverter().convertToStatement(pStmt, pCtxt) );
2027 // NB: this will invalidate current item.
2028 librdf_stream_next(pStream.get());
2031 return ret;
2034 extern "C"
2035 void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld)
2037 // fdo#64672 prevent raptor from setting global libxml2 error handlers
2038 raptor_world_set_flag(pRaptorWorld,
2039 RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE, 0);
2040 raptor_world_set_flag(pRaptorWorld,
2041 RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0);
2044 librdf_world *librdf_TypeConverter::createWorld_Lock() const
2046 // create and initialize world
2047 librdf_world *pWorld( librdf_new_world() );
2048 if (!pWorld) {
2049 throw uno::RuntimeException(
2050 u"librdf_TypeConverter::createWorld: librdf_new_world failed"_ustr,
2051 m_rRep);
2053 librdf_world_set_raptor_init_handler(pWorld, nullptr, &librdf_raptor_init);
2054 //FIXME logger, digest, features?
2055 xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs();
2056 librdf_world_open(pWorld);
2057 xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs();
2058 if (newprefs != origprefs) {
2059 // #i110523# restore libxslt global configuration
2060 // (gratuitously overwritten by raptor_init_parser_grddl_common)
2061 // (this is the only reason unordf is linked against libxslt)
2062 xsltSetDefaultSecurityPrefs(origprefs);
2064 return pWorld;
2067 librdf_storage *
2068 librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const
2070 librdf_storage *pStorage(
2071 // librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
2072 librdf_new_storage(i_pWorld, "hashes", nullptr,
2073 "contexts='yes',hash-type='memory'") );
2074 if (!pStorage) {
2075 throw uno::RuntimeException(
2076 u"librdf_TypeConverter::createStorage: librdf_new_storage failed"_ustr,
2077 m_rRep);
2079 return pStorage;
2082 librdf_model *librdf_TypeConverter::createModel_Lock(
2083 librdf_world *i_pWorld, librdf_storage * i_pStorage) const
2085 librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, nullptr) );
2086 if (!pRepository) {
2087 throw uno::RuntimeException(
2088 u"librdf_TypeConverter::createModel: librdf_new_model failed"_ustr,
2089 m_rRep);
2091 //FIXME
2092 #if 0
2094 librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS));
2095 librdf_node * contexts = librdf_model_get_feature(repository, ctxt);
2096 if (!contexts)
2097 throw;
2098 std::cout << "value of contexts feature: ";
2099 prtNode(contexts);
2100 std::cout << std::endl;
2101 // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...);
2102 safe_librdf_free_node(contexts);
2103 safe_librdf_free_uri(ctxt);
2105 #endif
2106 return pRepository;
2109 // this does NOT create a node, only URI
2110 librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld,
2111 OString const& i_rURI)
2113 librdf_uri *pURI( librdf_new_uri(i_pWorld,
2114 reinterpret_cast<const unsigned char *>(i_rURI.getStr())));
2115 if (!pURI) {
2116 throw uno::RuntimeException(
2117 u"librdf_TypeConverter::mkURI: librdf_new_uri failed"_ustr, nullptr);
2119 return pURI;
2122 // extract blank or URI node - call without Mutex locked
2123 std::shared_ptr<librdf_TypeConverter::Resource>
2124 librdf_TypeConverter::extractResource_NoLock(
2125 const uno::Reference< rdf::XResource > & i_xResource)
2127 if (!i_xResource.is()) {
2128 return std::shared_ptr<Resource>();
2130 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2131 if (xBlankNode.is()) {
2132 const OString label(
2133 OUStringToOString(xBlankNode->getStringValue(),
2134 RTL_TEXTENCODING_UTF8) );
2135 return std::make_shared<BlankNode>(label);
2136 } else { // assumption: everything else is URI
2137 const OString uri(
2138 OUStringToOString(i_xResource->getStringValue(),
2139 RTL_TEXTENCODING_UTF8) );
2140 return std::make_shared<URI>(uri);
2144 void
2145 librdf_TypeConverter::extractResourceToCacheKey_NoLock(
2146 const uno::Reference< rdf::XResource > & i_xResource, OUStringBuffer& rBuffer)
2148 if (!i_xResource.is()) {
2149 return;
2151 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2152 if (xBlankNode.is()) {
2153 rBuffer.append("BlankNode " + xBlankNode->getStringValue());
2154 } else { // assumption: everything else is URI
2155 rBuffer.append("URI " + i_xResource->getStringValue());
2159 // create blank or URI node
2160 librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld,
2161 Resource const*const i_pResource)
2163 if (!i_pResource) return nullptr;
2164 BlankNode const*const pBlankNode(
2165 dynamic_cast<BlankNode const*>(i_pResource));
2166 if (pBlankNode) {
2167 librdf_node *pNode(
2168 librdf_new_node_from_blank_identifier(i_pWorld,
2169 reinterpret_cast<const unsigned char*>(
2170 pBlankNode->value.getStr())));
2171 if (!pNode) {
2172 throw uno::RuntimeException(
2173 u"librdf_TypeConverter::mkResource: "
2174 "librdf_new_node_from_blank_identifier failed"_ustr, nullptr);
2176 return pNode;
2177 } else { // assumption: everything else is URI
2178 URI const*const pURI(dynamic_cast<URI const*>(i_pResource));
2179 assert(pURI);
2180 librdf_node *pNode(
2181 librdf_new_node_from_uri_string(i_pWorld,
2182 reinterpret_cast<const unsigned char*>(pURI->value.getStr())));
2183 if (!pNode) {
2184 throw uno::RuntimeException(
2185 u"librdf_TypeConverter::mkResource: "
2186 "librdf_new_node_from_uri_string failed"_ustr, nullptr);
2188 return pNode;
2192 // extract blank or URI or literal node - call without Mutex locked
2193 std::shared_ptr<librdf_TypeConverter::Node>
2194 librdf_TypeConverter::extractNode_NoLock(
2195 const uno::Reference< rdf::XNode > & i_xNode)
2197 if (!i_xNode.is()) {
2198 return std::shared_ptr<Node>();
2200 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2201 if (xResource.is()) {
2202 return extractResource_NoLock(xResource);
2204 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2205 OSL_ENSURE(xLiteral.is(),
2206 "mkNode: someone invented a new rdf.XNode and did not tell me");
2207 if (!xLiteral.is()) {
2208 return std::shared_ptr<Node>();
2210 const OString val(
2211 OUStringToOString(xLiteral->getValue(),
2212 RTL_TEXTENCODING_UTF8) );
2213 const OString lang(
2214 OUStringToOString(xLiteral->getLanguage(),
2215 RTL_TEXTENCODING_UTF8) );
2216 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2217 std::optional<OString> type;
2218 if (xType.is())
2220 type =
2221 OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8);
2223 return std::make_shared<Literal>(val, lang, type);
2226 // extract blank or URI or literal node - call without Mutex locked
2227 void
2228 librdf_TypeConverter::extractNodeToCacheKey_NoLock(
2229 const uno::Reference< rdf::XNode > & i_xNode,
2230 OUStringBuffer& rBuffer)
2232 if (!i_xNode.is()) {
2233 return;
2235 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2236 if (xResource.is()) {
2237 return extractResourceToCacheKey_NoLock(xResource, rBuffer);
2239 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2240 OSL_ENSURE(xLiteral.is(),
2241 "mkNode: someone invented a new rdf.XNode and did not tell me");
2242 if (!xLiteral.is()) {
2243 return;
2245 rBuffer.append("Literal " + xLiteral->getValue() + "\t" + xLiteral->getLanguage());
2246 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2247 if (xType.is())
2248 rBuffer.append("\t" + xType->getStringValue());
2251 // create blank or URI or literal node
2252 librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld,
2253 Node const*const i_pNode)
2255 if (!i_pNode) return nullptr;
2256 Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode));
2257 if (pResource) {
2258 return mkResource_Lock(i_pWorld, pResource);
2261 Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode));
2262 assert(pLiteral);
2263 librdf_node * ret(nullptr);
2264 if (pLiteral->language.isEmpty()) {
2265 if (!pLiteral->type) {
2266 ret = librdf_new_node_from_literal(i_pWorld,
2267 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2268 , nullptr, 0);
2269 } else {
2270 const std::shared_ptr<librdf_uri> pDatatype(
2271 mkURI_Lock(i_pWorld, *pLiteral->type),
2272 safe_librdf_free_uri);
2273 ret = librdf_new_node_from_typed_literal(i_pWorld,
2274 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2275 , nullptr, pDatatype.get());
2277 } else {
2278 if (!pLiteral->type) {
2279 ret = librdf_new_node_from_literal(i_pWorld,
2280 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2281 , pLiteral->language.getStr(), 0);
2282 } else {
2283 OSL_FAIL("mkNode: invalid literal");
2284 return nullptr;
2287 if (!ret) {
2288 throw uno::RuntimeException(
2289 u"librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed"_ustr, nullptr);
2291 return ret;
2294 // extract statement - call without Mutex locked
2295 librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock(
2296 const uno::Reference< rdf::XResource > & i_xSubject,
2297 const uno::Reference< rdf::XURI > & i_xPredicate,
2298 const uno::Reference< rdf::XNode > & i_xObject)
2300 std::shared_ptr<Resource> const pSubject(
2301 extractResource_NoLock(i_xSubject));
2302 std::shared_ptr<URI> const pPredicate(
2303 std::dynamic_pointer_cast<URI>(extractResource_NoLock(i_xPredicate)));
2304 std::shared_ptr<Node> const pObject(extractNode_NoLock(i_xObject));
2305 return Statement(pSubject, pPredicate, pObject);
2308 librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld,
2309 Statement const& i_rStatement)
2311 librdf_node *const pSubject(
2312 mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) );
2313 librdf_node* pPredicate(nullptr);
2314 librdf_node* pObject(nullptr);
2315 try {
2316 pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get());
2317 try {
2318 pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get());
2319 } catch (...) {
2320 safe_librdf_free_node(pPredicate);
2321 throw;
2323 } catch (...) {
2324 safe_librdf_free_node(pSubject);
2325 throw;
2327 // NB: this takes ownership of the nodes! (which is really ugly)
2328 librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld,
2329 pSubject, pPredicate, pObject) );
2330 if (!pStatement) {
2331 throw uno::RuntimeException(
2332 u"librdf_TypeConverter::mkStatement: "
2333 "librdf_new_statement_from_nodes failed"_ustr, nullptr);
2335 return pStatement;
2338 uno::Reference<rdf::XURI>
2339 librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const
2341 if (!i_pURI) return nullptr;
2342 const unsigned char* uri( librdf_uri_as_string(i_pURI) );
2343 if (!uri) {
2344 throw uno::RuntimeException(
2345 u"librdf_TypeConverter::convertToXURI: "
2346 "librdf_uri_as_string failed"_ustr, m_rRep);
2348 OUString uriU( OStringToOUString(
2349 std::string_view(reinterpret_cast<const char*>(uri)),
2350 RTL_TEXTENCODING_UTF8) );
2351 try {
2352 return rdf::URI::create(m_xContext, uriU);
2353 } catch (const lang::IllegalArgumentException &) {
2354 css::uno::Any anyEx = cppu::getCaughtException();
2355 throw lang::WrappedTargetRuntimeException(
2356 u"librdf_TypeConverter::convertToXURI: "
2357 "illegal uri"_ustr, m_rRep, anyEx);
2361 uno::Reference<rdf::XURI>
2362 librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const
2364 if (!i_pNode) return nullptr;
2365 if (librdf_node_is_resource(i_pNode)) {
2366 librdf_uri* pURI( librdf_node_get_uri(i_pNode) );
2367 if (!pURI) {
2368 throw uno::RuntimeException(
2369 u"librdf_TypeConverter::convertToXURI: "
2370 "resource has no uri"_ustr, m_rRep);
2372 return convertToXURI(pURI);
2373 } else {
2374 OSL_FAIL("convertToXURI: unknown librdf_node");
2375 return nullptr;
2379 uno::Reference<rdf::XResource>
2380 librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const
2382 if (!i_pNode) return nullptr;
2383 if (librdf_node_is_blank(i_pNode)) {
2384 const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) );
2385 if (!label) {
2386 throw uno::RuntimeException(
2387 u"librdf_TypeConverter::convertToXResource: "
2388 "blank node has no label"_ustr, m_rRep);
2390 OUString labelU( OStringToOUString(
2391 std::string_view(reinterpret_cast<const char*>(label)),
2392 RTL_TEXTENCODING_UTF8) );
2393 try {
2394 return rdf::BlankNode::create(m_xContext, labelU);
2395 } catch (const lang::IllegalArgumentException &) {
2396 css::uno::Any anyEx = cppu::getCaughtException();
2397 throw lang::WrappedTargetRuntimeException(
2398 u"librdf_TypeConverter::convertToXResource: "
2399 "illegal blank node label"_ustr, m_rRep, anyEx);
2401 } else {
2402 return convertToXURI(i_pNode);
2406 uno::Reference<rdf::XNode>
2407 librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const
2409 if (!i_pNode) return nullptr;
2410 if (!librdf_node_is_literal(i_pNode)) {
2411 return convertToXResource(i_pNode);
2413 const unsigned char* value( librdf_node_get_literal_value(i_pNode) );
2414 if (!value) {
2415 throw uno::RuntimeException(
2416 u"librdf_TypeConverter::convertToXNode: "
2417 "literal has no value"_ustr, m_rRep);
2419 const char * lang( librdf_node_get_literal_value_language(i_pNode) );
2420 librdf_uri* pType(
2421 librdf_node_get_literal_value_datatype_uri(i_pNode) );
2422 OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal");
2423 const OUString valueU( OStringToOUString(
2424 std::string_view(reinterpret_cast<const char*>(value)),
2425 RTL_TEXTENCODING_UTF8) );
2426 if (lang) {
2427 const OUString langU( OStringToOUString(
2428 std::string_view(lang),
2429 RTL_TEXTENCODING_UTF8) );
2430 return rdf::Literal::createWithLanguage(m_xContext, valueU, langU);
2431 } else if (pType) {
2432 uno::Reference<rdf::XURI> xType(convertToXURI(pType));
2433 OSL_ENSURE(xType.is(), "convertToXNode: null uri");
2434 return rdf::Literal::createWithType(m_xContext, valueU, xType);
2435 } else {
2436 return rdf::Literal::create(m_xContext, valueU);
2440 rdf::Statement
2441 librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt,
2442 librdf_node* i_pContext) const
2444 if (!i_pStmt) {
2445 throw uno::RuntimeException();
2447 return rdf::Statement(
2448 convertToXResource(librdf_statement_get_subject(i_pStmt)),
2449 convertToXURI(librdf_statement_get_predicate(i_pStmt)),
2450 convertToXNode(librdf_statement_get_object(i_pStmt)),
2451 convertToXURI(i_pContext));
2454 } // closing anonymous implementation namespace
2457 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2458 unoxml_rdfRepository_get_implementation(
2459 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
2461 return cppu::acquire(new librdf_Repository(context));
2464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */