Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / unoxml / source / rdf / librdf_repository.cxx
blob5e679b7cf3783f5403ffbac198562618e5db2d90
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 "librdf_repository.hxx"
22 #include <string.h>
24 #include <map>
25 #include <memory>
26 #include <set>
27 #include <iterator>
28 #include <algorithm>
29 #include <atomic>
31 #include <boost/optional.hpp>
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/XSeekableInputStream.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/URIs.hpp>
52 #include <com/sun/star/rdf/BlankNode.hpp>
53 #include <com/sun/star/rdf/URI.hpp>
54 #include <com/sun/star/rdf/Literal.hpp>
56 #include <rtl/ref.hxx>
57 #include <rtl/strbuf.hxx>
58 #include <rtl/ustrbuf.hxx>
59 #include <rtl/ustring.hxx>
60 #include <osl/diagnose.h>
61 #include <cppuhelper/exc_hlp.hxx>
62 #include <cppuhelper/implbase.hxx>
63 #include <cppuhelper/basemutex.hxx>
64 #include <cppuhelper/supportsservice.hxx>
65 #include <cppuhelper/weakref.hxx>
67 #include <comphelper/sequence.hxx>
68 #include <comphelper/xmltools.hxx>
70 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
72 /**
73 Implementation of the service com.sun.star.rdf.Repository.
75 This implementation uses the Redland RDF library (librdf).
77 There are several classes involved:
78 librdf_TypeConverter: helper class to convert data types redland <-> uno
79 librdf_Repository: the main repository, does almost all the work
80 librdf_NamedGraph: the XNamedGraph, forwards everything to repository
81 librdf_GraphResult: an XEnumeration<Statement>
82 librdf_QuerySelectResult: an XEnumeration<sequence<XNode>>
86 /// anonymous implementation namespace
87 namespace {
89 class librdf_NamedGraph;
90 class librdf_Repository;
92 using namespace ::com::sun::star;
94 typedef std::map< OUString, ::rtl::Reference<librdf_NamedGraph> >
95 NamedGraphMap_t;
97 const char s_sparql [] = "sparql";
98 const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/";
101 //FIXME: this approach is not ideal. can we use blank nodes instead?
102 bool isInternalContext(librdf_node *i_pNode) throw ()
104 OSL_ENSURE(i_pNode, "isInternalContext: context null");
105 OSL_ENSURE(librdf_node_is_resource(i_pNode),
106 "isInternalContext: context not resource");
107 if (i_pNode) {
108 librdf_uri *pURI(librdf_node_get_uri(i_pNode));
109 OSL_ENSURE(pURI, "isInternalContext: URI null");
110 if (pURI) {
111 unsigned char *pContextURI(librdf_uri_as_string(pURI));
112 assert(pContextURI && "isInternalContext: URI string null");
113 // if prefix matches reserved uri, it is RDFa context
114 if (!strncmp(reinterpret_cast<char *>(pContextURI),
115 s_nsOOo, sizeof(s_nsOOo)-1)) {
116 return true;
119 return false;
121 return true;
125 // n.b.: librdf destructor functions dereference null pointers!
126 // so they need to be wrapped to be usable with std::shared_ptr.
127 void safe_librdf_free_world(librdf_world *const world)
129 if (world) { librdf_free_world(world); }
131 void safe_librdf_free_model(librdf_model *const model)
133 if (model) { librdf_free_model(model); }
135 void safe_librdf_free_node(librdf_node* node)
137 if (node) { librdf_free_node(node); }
139 void safe_librdf_free_parser(librdf_parser *const parser)
141 if (parser) { librdf_free_parser(parser); }
143 void safe_librdf_free_query(librdf_query *const query)
145 if (query) { librdf_free_query(query); }
147 void
148 safe_librdf_free_query_results(librdf_query_results *const query_results)
150 if (query_results) { librdf_free_query_results(query_results); }
152 void safe_librdf_free_serializer(librdf_serializer *const serializer)
154 if (serializer) { librdf_free_serializer(serializer); }
156 void safe_librdf_free_statement(librdf_statement *const statement)
158 if (statement) { librdf_free_statement(statement); }
160 void safe_librdf_free_storage(librdf_storage *const storage)
162 if (storage) { librdf_free_storage(storage); }
164 void safe_librdf_free_stream(librdf_stream *const stream)
166 if (stream) { librdf_free_stream(stream); }
168 void safe_librdf_free_uri(librdf_uri *const uri)
170 if (uri) { librdf_free_uri(uri); }
174 /** converts between librdf types and UNO API types.
176 class librdf_TypeConverter
178 public:
180 // some wrapper classes to temporarily hold values of UNO XNodes
181 struct Node
183 virtual ~Node() {}
185 struct Resource : public Node { };
186 struct URI : public Resource
188 OString const value;
189 explicit URI(OString const& i_rValue)
190 : value(i_rValue)
193 struct BlankNode : public Resource
195 OString const value;
196 explicit BlankNode(OString const& i_rValue)
197 : value(i_rValue)
200 struct Literal : public Node
202 OString const value;
203 OString const language;
204 ::boost::optional<OString> const type;
205 Literal(OString const& i_rValue, OString const& i_rLanguage,
206 ::boost::optional<OString> const& i_rType)
207 : value(i_rValue)
208 , language(i_rLanguage)
209 , type(i_rType)
212 struct Statement
214 std::shared_ptr<Resource> const pSubject;
215 std::shared_ptr<URI> const pPredicate;
216 std::shared_ptr<Node> const pObject;
217 Statement(std::shared_ptr<Resource> const& i_pSubject,
218 std::shared_ptr<URI> const& i_pPredicate,
219 std::shared_ptr<Node> const& i_pObject)
220 : pSubject(i_pSubject)
221 , pPredicate(i_pPredicate)
222 , pObject(i_pObject)
226 librdf_TypeConverter(
227 uno::Reference< uno::XComponentContext > const & i_xContext,
228 librdf_Repository &i_rRep)
229 : m_xContext(i_xContext)
230 , m_rRep(i_rRep)
231 { };
233 librdf_world *createWorld_Lock() const;
234 librdf_storage *createStorage_Lock(librdf_world *i_pWorld) const;
235 librdf_model *createModel_Lock(librdf_world *i_pWorld,
236 librdf_storage * i_pStorage) const;
237 static librdf_uri* mkURI_Lock(librdf_world* i_pWorld,
238 const OString & i_rURI);
239 static librdf_node* mkResource_Lock(librdf_world* i_pWorld,
240 const Resource * i_pResource);
241 static librdf_node* mkNode_Lock(librdf_world* i_pWorld,
242 const Node * i_pNode);
243 static librdf_statement* mkStatement_Lock(librdf_world* i_pWorld,
244 Statement const& i_rStatement);
245 static std::shared_ptr<Resource> extractResource_NoLock(
246 const uno::Reference< rdf::XResource > & i_xResource);
247 static void extractResourceToCacheKey_NoLock(
248 const uno::Reference< rdf::XResource > & i_xResource,
249 OUStringBuffer& rBuf);
250 static std::shared_ptr<Node> extractNode_NoLock(
251 const uno::Reference< rdf::XNode > & i_xNode);
252 static void extractNodeToCacheKey_NoLock(
253 const uno::Reference< rdf::XNode > & i_xNode,
254 OUStringBuffer& rBuffer);
255 static Statement extractStatement_NoLock(
256 const uno::Reference< rdf::XResource > & i_xSubject,
257 const uno::Reference< rdf::XURI > & i_xPredicate,
258 const uno::Reference< rdf::XNode > & i_xObject);
259 uno::Reference<rdf::XURI> convertToXURI(librdf_uri* i_pURI) const;
260 uno::Reference<rdf::XURI> convertToXURI(librdf_node* i_pURI) const;
261 uno::Reference<rdf::XResource>
262 convertToXResource(librdf_node* i_pNode) const;
263 uno::Reference<rdf::XNode> convertToXNode(librdf_node* i_pNode) const;
264 rdf::Statement
265 convertToStatement(librdf_statement* i_pStmt, librdf_node* i_pContext)
266 const;
268 private:
269 uno::Reference< uno::XComponentContext > const m_xContext;
270 librdf_Repository & m_rRep;
274 /** implements the repository service.
276 class librdf_Repository:
277 // private ::cppu::BaseMutex,
278 public ::cppu::WeakImplHelper<
279 lang::XServiceInfo,
280 rdf::XDocumentRepository,
281 lang::XInitialization>
283 public:
285 explicit librdf_Repository(
286 uno::Reference< uno::XComponentContext > const & i_xContext);
287 virtual ~librdf_Repository() override;
289 // css::lang::XServiceInfo:
290 virtual OUString SAL_CALL getImplementationName() override;
291 virtual sal_Bool SAL_CALL supportsService(
292 const OUString & ServiceName) override;
293 virtual uno::Sequence< OUString > SAL_CALL
294 getSupportedServiceNames() override;
296 // css::rdf::XRepository:
297 virtual uno::Reference< rdf::XBlankNode > SAL_CALL createBlankNode() override;
298 virtual uno::Reference<rdf::XNamedGraph> SAL_CALL importGraph(
299 ::sal_Int16 i_Format,
300 const uno::Reference< io::XInputStream > & i_xInStream,
301 const uno::Reference< rdf::XURI > & i_xGraphName,
302 const uno::Reference< rdf::XURI > & i_xBaseURI) override;
303 virtual void SAL_CALL exportGraph(::sal_Int16 i_Format,
304 const uno::Reference< io::XOutputStream > & i_xOutStream,
305 const uno::Reference< rdf::XURI > & i_xGraphName,
306 const uno::Reference< rdf::XURI > & i_xBaseURI) override;
307 virtual uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
308 getGraphNames() override;
309 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL getGraph(
310 const uno::Reference< rdf::XURI > & i_xGraphName) override;
311 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL createGraph(
312 const uno::Reference< rdf::XURI > & i_xGraphName) override;
313 virtual void SAL_CALL destroyGraph(
314 const uno::Reference< rdf::XURI > & i_xGraphName) override;
315 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
316 const uno::Reference< rdf::XResource > & i_xSubject,
317 const uno::Reference< rdf::XURI > & i_xPredicate,
318 const uno::Reference< rdf::XNode > & i_xObject) override;
319 virtual uno::Reference< rdf::XQuerySelectResult > SAL_CALL
320 querySelect(const OUString & i_rQuery) override;
321 virtual uno::Reference< container::XEnumeration > SAL_CALL
322 queryConstruct(const OUString & i_rQuery) override;
323 virtual sal_Bool SAL_CALL queryAsk(const OUString & i_rQuery) override;
325 // css::rdf::XDocumentRepository:
326 virtual void SAL_CALL setStatementRDFa(
327 const uno::Reference< rdf::XResource > & i_xSubject,
328 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
329 const uno::Reference< rdf::XMetadatable > & i_xObject,
330 const OUString & i_rRDFaContent,
331 const uno::Reference< rdf::XURI > & i_xRDFaDatatype) override;
332 virtual void SAL_CALL removeStatementRDFa(
333 const uno::Reference< rdf::XMetadatable > & i_xElement) override;
334 virtual beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
335 getStatementRDFa(uno::Reference< rdf::XMetadatable > const& i_xElement) override;
336 virtual uno::Reference< container::XEnumeration > SAL_CALL
337 getStatementsRDFa(
338 const uno::Reference< rdf::XResource > & i_xSubject,
339 const uno::Reference< rdf::XURI > & i_xPredicate,
340 const uno::Reference< rdf::XNode > & i_xObject) override;
342 // css::lang::XInitialization:
343 virtual void SAL_CALL initialize(
344 const uno::Sequence< css::uno::Any > & i_rArguments) override;
346 // XNamedGraph forwards ---------------------------------------------
347 NamedGraphMap_t::iterator clearGraph_NoLock(
348 const OUString & i_rGraphName,
349 bool i_Internal = false );
350 NamedGraphMap_t::iterator clearGraph_Lock(
351 const OUString & i_rGraphName,
352 bool i_Internal);
353 void addStatementGraph_NoLock(
354 const uno::Reference< rdf::XResource > & i_xSubject,
355 const uno::Reference< rdf::XURI > & i_xPredicate,
356 const uno::Reference< rdf::XNode > & i_xObject,
357 const uno::Reference< rdf::XURI > & i_xName );
358 // throw (uno::RuntimeException, lang::IllegalArgumentException,
359 // container::NoSuchElementException, rdf::RepositoryException);
360 void addStatementGraph_Lock(
361 librdf_TypeConverter::Statement const& i_rStatement,
362 OUString const& i_rGraphName,
363 bool i_Internal);
364 void removeStatementsGraph_NoLock(
365 const uno::Reference< rdf::XResource > & i_xSubject,
366 const uno::Reference< rdf::XURI > & i_xPredicate,
367 const uno::Reference< rdf::XNode > & i_xObject,
368 const uno::Reference< rdf::XURI > & i_xName );
369 // throw (uno::RuntimeException, lang::IllegalArgumentException,
370 // container::NoSuchElementException, rdf::RepositoryException);
371 std::vector<rdf::Statement> getStatementsGraph_NoLock(
372 const uno::Reference< rdf::XResource > & i_xSubject,
373 const uno::Reference< rdf::XURI > & i_xPredicate,
374 const uno::Reference< rdf::XNode > & i_xObject,
375 const uno::Reference< rdf::XURI > & i_xName,
376 bool i_Internal = false );
377 // throw (uno::RuntimeException, lang::IllegalArgumentException,
378 // container::NoSuchElementException, rdf::RepositoryException);
380 const librdf_TypeConverter& getTypeConverter() const { return m_TypeConverter; };
382 private:
384 librdf_Repository(librdf_Repository const&) = delete;
385 librdf_Repository& operator=(librdf_Repository const&) = delete;
387 /// this is const, no need to lock m_aMutex to access it
388 uno::Reference< uno::XComponentContext > const m_xContext;
390 /// librdf global data
391 /** N.B.: The redland documentation gives the impression that you can have
392 as many librdf_worlds as you like. This is true in the same sense
393 that you can physically be in as many places as you like.
394 Well, you can, just not at the same time.
395 The ugly truth is that destroying a librdf_world kills a bunch
396 of static variables; other librdf_worlds become very unhappy
397 when they access these.
398 And of course this is not documented anywhere that I could find.
399 So we allocate a single world, and refcount that.
401 static std::shared_ptr<librdf_world> m_pWorld;
402 /// refcount
403 static sal_uInt32 m_NumInstances;
404 /// mutex for m_pWorld - redland is not as threadsafe as is often claimed
405 static osl::Mutex m_aMutex;
407 // NB: sequence of the shared pointers is important!
408 /// librdf repository storage
409 std::shared_ptr<librdf_storage> m_pStorage;
410 /// librdf repository model
411 std::shared_ptr<librdf_model> m_pModel;
413 /// all named graphs
414 NamedGraphMap_t m_NamedGraphs;
416 /// type conversion helper - stateless
417 librdf_TypeConverter const m_TypeConverter;
419 /// set of xml:ids of elements with xhtml:content
420 ::std::set< OUString > m_RDFaXHTMLContentSet;
424 /** result of operations that return a graph, i.e.,
425 an XEnumeration of statements.
427 class librdf_GraphResult:
428 public ::cppu::WeakImplHelper<
429 container::XEnumeration>
431 public:
433 librdf_GraphResult(librdf_Repository *i_pRepository,
434 ::osl::Mutex & i_rMutex,
435 std::shared_ptr<librdf_stream> const& i_pStream,
436 std::shared_ptr<librdf_node> const& i_pContext,
437 std::shared_ptr<librdf_query> const& i_pQuery =
438 std::shared_ptr<librdf_query>() )
439 : m_xRep(i_pRepository)
440 , m_rMutex(i_rMutex)
441 , m_pQuery(i_pQuery)
442 , m_pContext(i_pContext)
443 , m_pStream(i_pStream)
444 { };
446 virtual ~librdf_GraphResult() override
448 ::osl::MutexGuard g(m_rMutex); // lock mutex when destroying members
449 const_cast<std::shared_ptr<librdf_stream>& >(m_pStream).reset();
450 const_cast<std::shared_ptr<librdf_node>& >(m_pContext).reset();
451 const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset();
454 // css::container::XEnumeration:
455 virtual sal_Bool SAL_CALL hasMoreElements() override;
456 virtual uno::Any SAL_CALL nextElement() override;
458 private:
460 librdf_GraphResult(librdf_GraphResult const&) = delete;
461 librdf_GraphResult& operator=(librdf_GraphResult const&) = delete;
463 // NB: this is not a weak pointer: streams _must_ be deleted before the
464 // storage they point into, so we keep the repository alive here
465 // also, sequence is important: the stream must be destroyed first.
466 ::rtl::Reference< librdf_Repository > m_xRep;
467 // needed for synchronizing access to librdf (it doesn't do win32 threading)
468 ::osl::Mutex & m_rMutex;
469 // the query (in case this is a result of a graph query)
470 // not that the redland documentation spells this out explicitly, but
471 // queries must be freed only after all the results are completely read
472 std::shared_ptr<librdf_query> const m_pQuery;
473 std::shared_ptr<librdf_node> const m_pContext;
474 std::shared_ptr<librdf_stream> const m_pStream;
476 librdf_node* getContext_Lock() const;
480 // css::container::XEnumeration:
481 sal_Bool SAL_CALL
482 librdf_GraphResult::hasMoreElements()
484 ::osl::MutexGuard g(m_rMutex);
485 return m_pStream.get() && !librdf_stream_end(m_pStream.get());
488 librdf_node* librdf_GraphResult::getContext_Lock() const
490 if (!m_pStream.get() || librdf_stream_end(m_pStream.get()))
491 return nullptr;
492 librdf_node *pCtxt(
493 #if LIBRDF_VERSION >= 10012
494 librdf_stream_get_context2(m_pStream.get()) );
495 #else
496 static_cast<librdf_node *>(librdf_stream_get_context(m_pStream.get())) );
497 #endif
498 if (pCtxt)
499 return pCtxt;
500 return m_pContext.get();
503 css::uno::Any SAL_CALL
504 librdf_GraphResult::nextElement()
506 ::osl::MutexGuard g(m_rMutex);
507 if (m_pStream.get() && librdf_stream_end(m_pStream.get())) {
508 throw container::NoSuchElementException();
510 librdf_node * pCtxt = getContext_Lock();
512 librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) );
513 if (!pStmt) {
514 rdf::QueryException e(
515 "librdf_GraphResult::nextElement: "
516 "librdf_stream_get_object failed", *this);
517 throw lang::WrappedTargetException(
518 "librdf_GraphResult::nextElement: "
519 "librdf_stream_get_object failed", *this,
520 uno::makeAny(e));
522 // NB: pCtxt may be null here if this is result of a graph query
523 if (pCtxt && isInternalContext(pCtxt)) {
524 pCtxt = nullptr; // XML ID context is implementation detail!
526 rdf::Statement Stmt(
527 m_xRep->getTypeConverter().convertToStatement(pStmt, pCtxt) );
528 // NB: this will invalidate current item.
529 librdf_stream_next(m_pStream.get());
530 return uno::makeAny(Stmt);
534 /** result of operations that return a graph, i.e.,
535 an XEnumeration of statements.
537 class librdf_GraphResult2:
538 public ::cppu::WeakImplHelper<
539 container::XEnumeration>
541 public:
543 librdf_GraphResult2(std::vector<rdf::Statement> statements)
544 : m_vStatements(std::move(statements))
545 { };
547 // css::container::XEnumeration:
548 virtual sal_Bool SAL_CALL hasMoreElements() override;
549 virtual uno::Any SAL_CALL nextElement() override;
551 private:
553 std::vector<rdf::Statement> m_vStatements;
554 std::atomic<std::size_t> m_nIndex = 0;
558 // css::container::XEnumeration:
559 sal_Bool SAL_CALL
560 librdf_GraphResult2::hasMoreElements()
562 return m_nIndex < m_vStatements.size();
565 css::uno::Any SAL_CALL
566 librdf_GraphResult2::nextElement()
568 std::size_t const n = m_nIndex++;
569 if (m_vStatements.size() <= n)
571 m_nIndex = m_vStatements.size(); // avoid overflow
572 throw container::NoSuchElementException();
574 return uno::makeAny(m_vStatements[n]);
577 /** result of tuple queries ("SELECT").
579 class librdf_QuerySelectResult:
580 public ::cppu::WeakImplHelper<
581 rdf::XQuerySelectResult>
583 public:
585 librdf_QuerySelectResult(librdf_Repository *i_pRepository,
586 ::osl::Mutex & i_rMutex,
587 std::shared_ptr<librdf_query> const& i_pQuery,
588 std::shared_ptr<librdf_query_results> const& i_pQueryResult,
589 uno::Sequence< OUString > const& i_rBindingNames )
590 : m_xRep(i_pRepository)
591 , m_rMutex(i_rMutex)
592 , m_pQuery(i_pQuery)
593 , m_pQueryResult(i_pQueryResult)
594 , m_BindingNames(i_rBindingNames)
595 { };
597 virtual ~librdf_QuerySelectResult() override
599 ::osl::MutexGuard g(m_rMutex); // lock mutex when destroying members
600 const_cast<std::shared_ptr<librdf_query_results>& >(m_pQueryResult)
601 .reset();
602 const_cast<std::shared_ptr<librdf_query>& >(m_pQuery).reset();
605 // css::container::XEnumeration:
606 virtual sal_Bool SAL_CALL hasMoreElements() override;
607 virtual uno::Any SAL_CALL nextElement() override;
609 // css::rdf::XQuerySelectResult:
610 virtual uno::Sequence< OUString > SAL_CALL getBindingNames() override;
612 private:
614 librdf_QuerySelectResult(librdf_QuerySelectResult const&) = delete;
615 librdf_QuerySelectResult& operator=(librdf_QuerySelectResult const&) = delete;
617 // NB: this is not a weak pointer: streams _must_ be deleted before the
618 // storage they point into, so we keep the repository alive here
619 // also, sequence is important: the stream must be destroyed first.
620 ::rtl::Reference< librdf_Repository > m_xRep;
621 // needed for synchronizing access to librdf (it doesn't do win32 threading)
622 ::osl::Mutex & m_rMutex;
623 // not that the redland documentation spells this out explicitly, but
624 // queries must be freed only after all the results are completely read
625 std::shared_ptr<librdf_query> const m_pQuery;
626 std::shared_ptr<librdf_query_results> const m_pQueryResult;
627 uno::Sequence< OUString > const m_BindingNames;
631 // css::container::XEnumeration:
632 sal_Bool SAL_CALL
633 librdf_QuerySelectResult::hasMoreElements()
635 ::osl::MutexGuard g(m_rMutex);
636 return !librdf_query_results_finished(m_pQueryResult.get());
639 class NodeArrayDeleter
641 const int m_Count;
643 public:
644 explicit NodeArrayDeleter(int i_Count) : m_Count(i_Count) { }
646 void operator() (librdf_node** io_pArray) const throw ()
648 std::for_each(io_pArray, io_pArray + m_Count, safe_librdf_free_node);
649 delete[] io_pArray;
653 css::uno::Any SAL_CALL
654 librdf_QuerySelectResult::nextElement()
656 ::osl::MutexGuard g(m_rMutex);
657 if (librdf_query_results_finished(m_pQueryResult.get())) {
658 throw container::NoSuchElementException();
660 sal_Int32 count(m_BindingNames.getLength());
661 OSL_ENSURE(count >= 0, "negative length?");
662 std::shared_ptr<librdf_node*> const pNodes(new librdf_node*[count],
663 NodeArrayDeleter(count));
664 for (int i = 0; i < count; ++i) {
665 pNodes.get()[i] = nullptr;
667 if (librdf_query_results_get_bindings(m_pQueryResult.get(), nullptr,
668 pNodes.get()))
670 rdf::QueryException e(
671 "librdf_QuerySelectResult::nextElement: "
672 "librdf_query_results_get_bindings failed", *this);
673 throw lang::WrappedTargetException(
674 "librdf_QuerySelectResult::nextElement: "
675 "librdf_query_results_get_bindings failed", *this,
676 uno::makeAny(e));
678 uno::Sequence< uno::Reference< rdf::XNode > > ret(count);
679 for (int i = 0; i < count; ++i) {
680 ret[i] = m_xRep->getTypeConverter().convertToXNode(pNodes.get()[i]);
682 // NB: this will invalidate current item.
683 librdf_query_results_next(m_pQueryResult.get());
684 return uno::makeAny(ret);
687 // css::rdf::XQuerySelectResult:
688 uno::Sequence< OUString > SAL_CALL
689 librdf_QuerySelectResult::getBindingNames()
691 // const - no lock needed
692 return m_BindingNames;
696 /** represents a named graph, and forwards all the work to repository.
698 class librdf_NamedGraph:
699 public ::cppu::WeakImplHelper<
700 rdf::XNamedGraph>
702 public:
703 librdf_NamedGraph(librdf_Repository * i_pRep,
704 uno::Reference<rdf::XURI> const & i_xName)
705 : m_wRep(i_pRep)
706 , m_pRep(i_pRep)
707 , m_xName(i_xName)
708 { };
710 // css::rdf::XNode:
711 virtual OUString SAL_CALL getStringValue() override;
713 // css::rdf::XURI:
714 virtual OUString SAL_CALL getNamespace() override;
715 virtual OUString SAL_CALL getLocalName() override;
717 // css::rdf::XNamedGraph:
718 virtual uno::Reference<rdf::XURI> SAL_CALL getName() override;
719 virtual void SAL_CALL clear() override;
720 virtual void SAL_CALL addStatement(
721 const uno::Reference< rdf::XResource > & i_xSubject,
722 const uno::Reference< rdf::XURI > & i_xPredicate,
723 const uno::Reference< rdf::XNode > & i_xObject) override;
724 virtual void SAL_CALL removeStatements(
725 const uno::Reference< rdf::XResource > & i_xSubject,
726 const uno::Reference< rdf::XURI > & i_xPredicate,
727 const uno::Reference< rdf::XNode > & i_xObject) override;
728 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
729 const uno::Reference< rdf::XResource > & i_xSubject,
730 const uno::Reference< rdf::XURI > & i_xPredicate,
731 const uno::Reference< rdf::XNode > & i_xObject) override;
733 private:
735 librdf_NamedGraph(librdf_NamedGraph const&) = delete;
736 librdf_NamedGraph& operator=(librdf_NamedGraph const&) = delete;
738 static OUString createCacheKey_NoLock(
739 const uno::Reference< rdf::XResource > & i_xSubject,
740 const uno::Reference< rdf::XURI > & i_xPredicate,
741 const uno::Reference< rdf::XNode > & i_xObject);
743 /// weak reference: this is needed to check if m_pRep is valid
744 uno::WeakReference< rdf::XRepository > const m_wRep;
745 librdf_Repository *const m_pRep;
746 uno::Reference< rdf::XURI > const m_xName;
748 /// Querying is rather slow, so cache the results.
749 std::map<OUString, std::vector<rdf::Statement>> m_aStatementsCache;
750 ::osl::Mutex m_CacheMutex;
754 // css::rdf::XNode:
755 OUString SAL_CALL librdf_NamedGraph::getStringValue()
757 return m_xName->getStringValue();
760 // css::rdf::XURI:
761 OUString SAL_CALL librdf_NamedGraph::getNamespace()
763 return m_xName->getNamespace();
766 OUString SAL_CALL librdf_NamedGraph::getLocalName()
768 return m_xName->getLocalName();
771 // css::rdf::XNamedGraph:
772 uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName()
774 return m_xName;
777 void SAL_CALL librdf_NamedGraph::clear()
779 uno::Reference< rdf::XRepository > xRep( m_wRep );
780 if (!xRep.is()) {
781 throw rdf::RepositoryException(
782 "librdf_NamedGraph::clear: repository is gone", *this);
784 const OUString contextU( m_xName->getStringValue() );
785 try {
786 m_pRep->clearGraph_NoLock(contextU);
787 } catch (lang::IllegalArgumentException & ex) {
788 css::uno::Any anyEx = cppu::getCaughtException();
789 throw lang::WrappedTargetRuntimeException( ex.Message,
790 *this, anyEx );
792 ::osl::MutexGuard g(m_CacheMutex);
793 m_aStatementsCache.clear();
796 void SAL_CALL librdf_NamedGraph::addStatement(
797 const uno::Reference< rdf::XResource > & i_xSubject,
798 const uno::Reference< rdf::XURI > & i_xPredicate,
799 const uno::Reference< rdf::XNode > & i_xObject)
801 uno::Reference< rdf::XRepository > xRep( m_wRep );
802 if (!xRep.is()) {
803 throw rdf::RepositoryException(
804 "librdf_NamedGraph::addStatement: repository is gone", *this);
807 ::osl::MutexGuard g(m_CacheMutex);
808 m_aStatementsCache.clear();
810 m_pRep->addStatementGraph_NoLock(
811 i_xSubject, i_xPredicate, i_xObject, m_xName);
814 void SAL_CALL librdf_NamedGraph::removeStatements(
815 const uno::Reference< rdf::XResource > & i_xSubject,
816 const uno::Reference< rdf::XURI > & i_xPredicate,
817 const uno::Reference< rdf::XNode > & i_xObject)
819 uno::Reference< rdf::XRepository > xRep( m_wRep );
820 if (!xRep.is()) {
821 throw rdf::RepositoryException(
822 "librdf_NamedGraph::removeStatements: repository is gone", *this);
825 ::osl::MutexGuard g(m_CacheMutex);
826 m_aStatementsCache.clear();
828 m_pRep->removeStatementsGraph_NoLock(
829 i_xSubject, i_xPredicate, i_xObject, m_xName);
832 OUString librdf_NamedGraph::createCacheKey_NoLock(
833 const uno::Reference< rdf::XResource > & i_xSubject,
834 const uno::Reference< rdf::XURI > & i_xPredicate,
835 const uno::Reference< rdf::XNode > & i_xObject)
837 OUStringBuffer cacheKey(256);
838 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xSubject, cacheKey);
839 cacheKey.append("\t");
840 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xPredicate, cacheKey);
841 cacheKey.append("\t");
842 librdf_TypeConverter::extractNodeToCacheKey_NoLock(i_xObject, cacheKey);
843 return cacheKey.makeStringAndClear();
846 uno::Reference< container::XEnumeration > SAL_CALL
847 librdf_NamedGraph::getStatements(
848 const uno::Reference< rdf::XResource > & i_xSubject,
849 const uno::Reference< rdf::XURI > & i_xPredicate,
850 const uno::Reference< rdf::XNode > & i_xObject)
852 OUString cacheKey = createCacheKey_NoLock(i_xSubject, i_xPredicate, i_xObject);
854 ::osl::MutexGuard g(m_CacheMutex);
855 auto it = m_aStatementsCache.find(cacheKey);
856 if (it != m_aStatementsCache.end()) {
857 return new librdf_GraphResult2(it->second);
861 uno::Reference< rdf::XRepository > xRep( m_wRep );
862 if (!xRep.is()) {
863 throw rdf::RepositoryException(
864 "librdf_NamedGraph::getStatements: repository is gone", *this);
866 std::vector<rdf::Statement> vStatements = m_pRep->getStatementsGraph_NoLock(
867 i_xSubject, i_xPredicate, i_xObject, m_xName);
870 ::osl::MutexGuard g(m_CacheMutex);
871 m_aStatementsCache.emplace(cacheKey, vStatements);
873 return new librdf_GraphResult2(vStatements);
877 std::shared_ptr<librdf_world> librdf_Repository::m_pWorld;
878 sal_uInt32 librdf_Repository::m_NumInstances = 0;
879 osl::Mutex librdf_Repository::m_aMutex;
881 librdf_Repository::librdf_Repository(
882 uno::Reference< uno::XComponentContext > const & i_xContext)
883 : /*BaseMutex(),*/ m_xContext(i_xContext)
884 // m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ),
885 , m_pStorage(static_cast<librdf_storage*>(nullptr), safe_librdf_free_storage)
886 , m_pModel (static_cast<librdf_model *>(nullptr), safe_librdf_free_model )
887 , m_NamedGraphs()
888 , m_TypeConverter(i_xContext, *this)
890 OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context");
892 ::osl::MutexGuard g(m_aMutex);
893 if (!m_NumInstances++) {
894 m_pWorld.reset(m_TypeConverter.createWorld_Lock(),
895 safe_librdf_free_world);
899 librdf_Repository::~librdf_Repository()
901 ::osl::MutexGuard g(m_aMutex);
903 // must destroy these before world!
904 m_pModel.reset();
905 m_pStorage.reset();
907 // FIXME: so it turns out that calling librdf_free_world will
908 // (via raptor_sax2_finish) call xmlCleanupParser, which will
909 // free libxml2's globals! ARRRGH!!! => never call librdf_free_world
910 #if 0
911 if (!--m_NumInstances) {
912 m_pWorld.reset();
914 #endif
917 // com.sun.star.uno.XServiceInfo:
918 OUString SAL_CALL librdf_Repository::getImplementationName()
920 return comp_librdf_Repository::_getImplementationName();
923 sal_Bool SAL_CALL librdf_Repository::supportsService(
924 OUString const & serviceName)
926 return cppu::supportsService(this, serviceName);
929 uno::Sequence< OUString > SAL_CALL
930 librdf_Repository::getSupportedServiceNames()
932 return comp_librdf_Repository::_getSupportedServiceNames();
935 // css::rdf::XRepository:
936 uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode()
938 ::osl::MutexGuard g(m_aMutex);
939 const std::shared_ptr<librdf_node> pNode(
940 librdf_new_node_from_blank_identifier(m_pWorld.get(), nullptr),
941 safe_librdf_free_node);
942 if (!pNode) {
943 throw uno::RuntimeException(
944 "librdf_Repository::createBlankNode: "
945 "librdf_new_node_from_blank_identifier failed", *this);
947 const unsigned char * id (librdf_node_get_blank_identifier(pNode.get()));
948 if (!id) {
949 throw uno::RuntimeException(
950 "librdf_Repository::createBlankNode: "
951 "librdf_node_get_blank_identifier failed", *this);
953 const OUString nodeID(OUString::createFromAscii(
954 reinterpret_cast<const char *>(id)));
955 try {
956 return rdf::BlankNode::create(m_xContext, nodeID);
957 } catch (const lang::IllegalArgumentException &) {
958 css::uno::Any anyEx = cppu::getCaughtException();
959 throw lang::WrappedTargetRuntimeException(
960 "librdf_Repository::createBlankNode: "
961 "illegal blank node label", *this, anyEx);
965 //void SAL_CALL
966 uno::Reference<rdf::XNamedGraph> SAL_CALL
967 librdf_Repository::importGraph(::sal_Int16 i_Format,
968 const uno::Reference< io::XInputStream > & i_xInStream,
969 const uno::Reference< rdf::XURI > & i_xGraphName,
970 const uno::Reference< rdf::XURI > & i_xBaseURI)
972 if (!i_xInStream.is()) {
973 throw lang::IllegalArgumentException(
974 "librdf_Repository::importGraph: stream is null", *this, 1);
976 //FIXME: other formats
977 if (i_Format != rdf::FileFormat::RDF_XML) {
978 throw datatransfer::UnsupportedFlavorException(
979 "librdf_Repository::importGraph: file format not supported", *this);
981 if (!i_xGraphName.is()) {
982 throw lang::IllegalArgumentException(
983 "librdf_Repository::importGraph: graph name is null", *this, 2);
985 if (i_xGraphName->getStringValue().startsWith(s_nsOOo))
987 throw lang::IllegalArgumentException(
988 "librdf_Repository::importGraph: URI is reserved", *this, 0);
990 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
991 throw lang::IllegalArgumentException(
992 "librdf_Repository::importGraph: base URI is null", *this, 3);
994 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
995 const OUString baseURIU( i_xBaseURI->getStringValue() );
996 if (baseURIU.indexOf('#') >= 0) {
997 throw lang::IllegalArgumentException(
998 "librdf_Repository::importGraph: base URI is not absolute", *this, 3);
1001 const OUString contextU( i_xGraphName->getStringValue() );
1003 uno::Sequence<sal_Int8> buf;
1004 uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
1005 // UGLY: if only redland could read streams...
1006 const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
1007 // exceptions are propagated
1008 i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
1010 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1012 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1013 throw container::ElementExistException(
1014 "librdf_Repository::importGraph: graph with given URI exists", *this);
1016 const OString context(
1017 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1019 const std::shared_ptr<librdf_node> pContext(
1020 librdf_new_node_from_uri_string(m_pWorld.get(),
1021 reinterpret_cast<const unsigned char*> (context.getStr())),
1022 safe_librdf_free_node);
1023 if (!pContext) {
1024 throw uno::RuntimeException(
1025 "librdf_Repository::importGraph: librdf_new_node_from_uri_string failed", *this);
1028 const OString baseURI(
1029 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1030 const std::shared_ptr<librdf_uri> pBaseURI(
1031 librdf_new_uri(m_pWorld.get(),
1032 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1033 safe_librdf_free_uri);
1034 if (!pBaseURI) {
1035 throw uno::RuntimeException( "librdf_Repository::importGraph: librdf_new_uri failed", *this);
1038 const std::shared_ptr<librdf_parser> pParser(
1039 librdf_new_parser(m_pWorld.get(), "rdfxml", nullptr, nullptr),
1040 safe_librdf_free_parser);
1041 if (!pParser) {
1042 throw uno::RuntimeException(
1043 "librdf_Repository::importGraph: "
1044 "librdf_new_parser failed", *this);
1047 const std::shared_ptr<librdf_stream> pStream(
1048 librdf_parser_parse_counted_string_as_stream(pParser.get(),
1049 reinterpret_cast<const unsigned char*>(buf.getConstArray()),
1050 buf.getLength(), pBaseURI.get()),
1051 safe_librdf_free_stream);
1052 if (!pStream) {
1053 throw rdf::ParseException(
1054 "librdf_Repository::importGraph: "
1055 "librdf_parser_parse_counted_string_as_stream failed", *this);
1057 rtl::Reference<librdf_NamedGraph> const pGraph(
1058 new librdf_NamedGraph(this, i_xGraphName));
1059 m_NamedGraphs.insert(std::make_pair(contextU, pGraph));
1060 if (librdf_model_context_add_statements(m_pModel.get(),
1061 pContext.get(), pStream.get())) {
1062 throw rdf::RepositoryException(
1063 "librdf_Repository::importGraph: "
1064 "librdf_model_context_add_statements failed", *this);
1067 return uno::Reference<rdf::XNamedGraph>(pGraph.get());
1070 void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
1072 if (!length)
1073 return;
1075 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream,
1076 uno::UNO_QUERY);
1078 bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData();
1080 // exceptions are propagated
1081 if (!bAddChaff)
1083 const uno::Sequence<sal_Int8> buf(
1084 reinterpret_cast<sal_Int8*>(pBuffer), length);
1085 rStream->writeBytes(buf);
1087 else
1089 unsigned char *postcomment =
1090 reinterpret_cast<unsigned char*>(strchr(reinterpret_cast<char*>(pBuffer), '\n'));
1091 if (postcomment != nullptr)
1093 ++postcomment;
1095 size_t preamblelen = postcomment - pBuffer;
1097 uno::Sequence<sal_Int8> buf(
1098 reinterpret_cast<sal_Int8*>(pBuffer), preamblelen);
1099 rStream->writeBytes(buf);
1101 OStringBuffer aComment;
1102 aComment.append("<!--");
1103 aComment.append(comphelper::xml::makeXMLChaff());
1104 aComment.append("-->");
1106 buf = uno::Sequence<sal_Int8>(
1107 reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength());
1108 rStream->writeBytes(buf);
1110 buf = uno::Sequence<sal_Int8>(
1111 reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen);
1112 rStream->writeBytes(buf);
1117 void SAL_CALL
1118 librdf_Repository::exportGraph(::sal_Int16 i_Format,
1119 const uno::Reference< io::XOutputStream > & i_xOutStream,
1120 const uno::Reference< rdf::XURI > & i_xGraphName,
1121 const uno::Reference< rdf::XURI > & i_xBaseURI)
1123 if (!i_xOutStream.is()) {
1124 throw lang::IllegalArgumentException(
1125 "librdf_Repository::exportGraph: stream is null", *this, 1);
1127 // FIXME: other formats
1128 if (i_Format != rdf::FileFormat::RDF_XML) {
1129 throw datatransfer::UnsupportedFlavorException(
1130 "librdf_Repository::exportGraph: "
1131 "file format not supported", *this);
1133 if (!i_xGraphName.is()) {
1134 throw lang::IllegalArgumentException(
1135 "librdf_Repository::exportGraph: "
1136 "graph name is null", *this, 2);
1138 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
1139 throw lang::IllegalArgumentException(
1140 "librdf_Repository::exportGraph: "
1141 "base URI is null", *this, 3);
1143 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
1144 const OUString baseURIU( i_xBaseURI->getStringValue() );
1145 if (baseURIU.indexOf('#') >= 0) {
1146 throw lang::IllegalArgumentException(
1147 "librdf_Repository::exportGraph: "
1148 "base URI is not absolute", *this, 3);
1151 const OUString contextU( i_xGraphName->getStringValue() );
1153 ::osl::ClearableMutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1155 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1156 throw container::NoSuchElementException(
1157 "librdf_Repository::exportGraph: "
1158 "no graph with given URI exists", *this);
1160 const OString context(
1161 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1163 const std::shared_ptr<librdf_node> pContext(
1164 librdf_new_node_from_uri_string(m_pWorld.get(),
1165 reinterpret_cast<const unsigned char*> (context.getStr())),
1166 safe_librdf_free_node);
1167 if (!pContext) {
1168 throw uno::RuntimeException(
1169 "librdf_Repository::exportGraph: "
1170 "librdf_new_node_from_uri_string failed", *this);
1172 const OString baseURI(
1173 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1174 const std::shared_ptr<librdf_uri> pBaseURI(
1175 librdf_new_uri(m_pWorld.get(),
1176 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1177 safe_librdf_free_uri);
1178 if (!pBaseURI) {
1179 throw uno::RuntimeException(
1180 "librdf_Repository::exportGraph: "
1181 "librdf_new_uri failed", *this);
1184 const std::shared_ptr<librdf_stream> pStream(
1185 librdf_model_context_as_stream(m_pModel.get(), pContext.get()),
1186 safe_librdf_free_stream);
1187 if (!pStream) {
1188 throw rdf::RepositoryException(
1189 "librdf_Repository::exportGraph: "
1190 "librdf_model_context_as_stream failed", *this);
1192 const char * const format("rdfxml");
1193 // #i116443#: abbrev breaks when certain URIs are used as data types
1194 // const char *format("rdfxml-abbrev");
1195 const std::shared_ptr<librdf_serializer> pSerializer(
1196 librdf_new_serializer(m_pWorld.get(), format, nullptr, nullptr),
1197 safe_librdf_free_serializer);
1198 if (!pSerializer) {
1199 throw uno::RuntimeException(
1200 "librdf_Repository::exportGraph: "
1201 "librdf_new_serializer failed", *this);
1204 const std::shared_ptr<librdf_uri> pRelativeURI(
1205 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1206 ("http://feature.librdf.org/raptor-relativeURIs")),
1207 safe_librdf_free_uri);
1208 const std::shared_ptr<librdf_uri> pWriteBaseURI(
1209 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1210 ("http://feature.librdf.org/raptor-writeBaseURI")),
1211 safe_librdf_free_uri);
1212 const std::shared_ptr<librdf_node> p0(
1213 librdf_new_node_from_literal(m_pWorld.get(),
1214 reinterpret_cast<const unsigned char*> ("0"), nullptr, 0),
1215 safe_librdf_free_node);
1216 const std::shared_ptr<librdf_node> p1(
1217 librdf_new_node_from_literal(m_pWorld.get(),
1218 reinterpret_cast<const unsigned char*> ("1"), nullptr, 0),
1219 safe_librdf_free_node);
1220 if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) {
1221 throw uno::RuntimeException(
1222 "librdf_Repository::exportGraph: "
1223 "librdf_new_uri or librdf_new_node_from_literal failed", *this);
1226 // make URIs relative to base URI
1227 if (librdf_serializer_set_feature(pSerializer.get(),
1228 pRelativeURI.get(), p1.get()))
1230 throw uno::RuntimeException(
1231 "librdf_Repository::exportGraph: "
1232 "librdf_serializer_set_feature relativeURIs failed", *this);
1234 // but do not write the base URI to the file!
1235 if (librdf_serializer_set_feature(pSerializer.get(),
1236 pWriteBaseURI.get(), p0.get()))
1238 throw uno::RuntimeException(
1239 "librdf_Repository::exportGraph: "
1240 "librdf_serializer_set_feature writeBaseURI failed", *this);
1243 size_t length;
1244 const std::shared_ptr<unsigned char> pBuf(
1245 librdf_serializer_serialize_stream_to_counted_string(
1246 pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free);
1247 if (!pBuf) {
1248 throw rdf::RepositoryException(
1249 "librdf_Repository::exportGraph: "
1250 "librdf_serializer_serialize_stream_to_counted_string failed",
1251 *this);
1254 g.clear(); // release Mutex before calling i_xOutStream methods
1256 addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
1259 uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
1260 librdf_Repository::getGraphNames()
1262 ::osl::MutexGuard g(m_aMutex);
1263 ::std::vector< uno::Reference<rdf::XURI> > ret;
1264 std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(),
1265 std::back_inserter(ret),
1266 [](std::pair<OUString, ::rtl::Reference<librdf_NamedGraph>> const& it)
1267 { return it.second->getName(); });
1268 return comphelper::containerToSequence(ret);
1271 uno::Reference< rdf::XNamedGraph > SAL_CALL
1272 librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1274 if (!i_xGraphName.is()) {
1275 throw lang::IllegalArgumentException(
1276 "librdf_Repository::getGraph: URI is null", *this, 0);
1278 const OUString contextU( i_xGraphName->getStringValue() );
1280 ::osl::MutexGuard g(m_aMutex);
1281 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
1282 if (iter != m_NamedGraphs.end()) {
1283 return uno::Reference<rdf::XNamedGraph>(iter->second.get());
1284 } else {
1285 return nullptr;
1289 uno::Reference< rdf::XNamedGraph > SAL_CALL
1290 librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1292 if (!i_xGraphName.is()) {
1293 throw lang::IllegalArgumentException(
1294 "librdf_Repository::createGraph: URI is null", *this, 0);
1297 const OUString contextU( i_xGraphName->getStringValue() );
1298 if (contextU.startsWith(s_nsOOo))
1300 throw lang::IllegalArgumentException(
1301 "librdf_Repository::createGraph: URI is reserved", *this, 0);
1304 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1306 // NB: librdf does not have a concept of graphs as such;
1307 // a librdf named graph exists iff the model contains a statement with
1308 // the graph name as context
1310 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1311 throw container::ElementExistException(
1312 "librdf_Repository::createGraph: graph with given URI exists", *this);
1314 m_NamedGraphs.insert(std::make_pair(contextU,
1315 new librdf_NamedGraph(this, i_xGraphName)));
1316 return uno::Reference<rdf::XNamedGraph>(
1317 m_NamedGraphs.find(contextU)->second.get());
1320 void SAL_CALL
1321 librdf_Repository::destroyGraph(
1322 const uno::Reference< rdf::XURI > & i_xGraphName)
1324 if (!i_xGraphName.is()) {
1325 throw lang::IllegalArgumentException(
1326 "librdf_Repository::destroyGraph: URI is null", *this, 0);
1328 const OUString contextU( i_xGraphName->getStringValue() );
1330 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1332 const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) );
1333 m_NamedGraphs.erase(iter);
1336 bool isMetadatableWithoutMetadata(
1337 uno::Reference<uno::XInterface> const & i_xNode)
1339 const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY );
1340 return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty());
1343 uno::Reference< container::XEnumeration > SAL_CALL
1344 librdf_Repository::getStatements(
1345 const uno::Reference< rdf::XResource > & i_xSubject,
1346 const uno::Reference< rdf::XURI > & i_xPredicate,
1347 const uno::Reference< rdf::XNode > & i_xObject)
1349 if (isMetadatableWithoutMetadata(i_xSubject) ||
1350 isMetadatableWithoutMetadata(i_xPredicate) ||
1351 isMetadatableWithoutMetadata(i_xObject))
1353 return new librdf_GraphResult(this, m_aMutex,
1354 std::shared_ptr<librdf_stream>(),
1355 std::shared_ptr<librdf_node>());
1358 librdf_TypeConverter::Statement const stmt(
1359 librdf_TypeConverter::extractStatement_NoLock(
1360 i_xSubject, i_xPredicate, i_xObject));
1362 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1364 const std::shared_ptr<librdf_statement> pStatement(
1365 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1366 safe_librdf_free_statement);
1367 OSL_ENSURE(pStatement, "mkStatement failed");
1369 const std::shared_ptr<librdf_stream> pStream(
1370 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1371 safe_librdf_free_stream);
1372 if (!pStream) {
1373 throw rdf::RepositoryException(
1374 "librdf_Repository::getStatements: "
1375 "librdf_model_find_statements failed", *this);
1378 return new librdf_GraphResult(this, m_aMutex, pStream,
1379 std::shared_ptr<librdf_node>());
1383 uno::Reference< rdf::XQuerySelectResult > SAL_CALL
1384 librdf_Repository::querySelect(const OUString & i_rQuery)
1386 ::osl::MutexGuard g(m_aMutex);
1387 const OString query(
1388 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1389 const std::shared_ptr<librdf_query> pQuery(
1390 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1391 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1392 safe_librdf_free_query);
1393 if (!pQuery) {
1394 throw rdf::QueryException(
1395 "librdf_Repository::querySelect: "
1396 "librdf_new_query failed", *this);
1398 const std::shared_ptr<librdf_query_results> pResults(
1399 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1400 safe_librdf_free_query_results);
1401 if (!pResults || !librdf_query_results_is_bindings(pResults.get())) {
1402 throw rdf::QueryException(
1403 "librdf_Repository::querySelect: "
1404 "query result is null or not bindings", *this);
1407 const int count( librdf_query_results_get_bindings_count(pResults.get()) );
1408 if (count < 0) {
1409 throw rdf::QueryException(
1410 "librdf_Repository::querySelect: "
1411 "librdf_query_results_get_bindings_count failed", *this);
1413 uno::Sequence< OUString > names(count);
1414 for (int i = 0; i < count; ++i) {
1415 const char* name( librdf_query_results_get_binding_name(
1416 pResults.get(), i) );
1417 if (!name) {
1418 throw rdf::QueryException(
1419 "librdf_Repository::querySelect: binding is null", *this);
1422 names[i] = OUString::createFromAscii(name);
1425 return new librdf_QuerySelectResult(this, m_aMutex,
1426 pQuery, pResults, names);
1429 uno::Reference< container::XEnumeration > SAL_CALL
1430 librdf_Repository::queryConstruct(const OUString & i_rQuery)
1432 ::osl::MutexGuard g(m_aMutex);
1433 const OString query(
1434 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1435 const std::shared_ptr<librdf_query> pQuery(
1436 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1437 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1438 safe_librdf_free_query);
1439 if (!pQuery) {
1440 throw rdf::QueryException(
1441 "librdf_Repository::queryConstruct: "
1442 "librdf_new_query failed", *this);
1444 const std::shared_ptr<librdf_query_results> pResults(
1445 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1446 safe_librdf_free_query_results);
1447 if (!pResults || !librdf_query_results_is_graph(pResults.get())) {
1448 throw rdf::QueryException(
1449 "librdf_Repository::queryConstruct: "
1450 "query result is null or not graph", *this);
1452 const std::shared_ptr<librdf_stream> pStream(
1453 librdf_query_results_as_stream(pResults.get()),
1454 safe_librdf_free_stream);
1455 if (!pStream) {
1456 throw rdf::QueryException(
1457 "librdf_Repository::queryConstruct: "
1458 "librdf_query_results_as_stream failed", *this);
1461 return new librdf_GraphResult(this, m_aMutex, pStream,
1462 std::shared_ptr<librdf_node>(), pQuery);
1465 sal_Bool SAL_CALL
1466 librdf_Repository::queryAsk(const OUString & i_rQuery)
1468 ::osl::MutexGuard g(m_aMutex);
1470 const OString query(
1471 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1472 const std::shared_ptr<librdf_query> pQuery(
1473 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1474 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1475 safe_librdf_free_query);
1476 if (!pQuery) {
1477 throw rdf::QueryException(
1478 "librdf_Repository::queryAsk: "
1479 "librdf_new_query failed", *this);
1481 const std::shared_ptr<librdf_query_results> pResults(
1482 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1483 safe_librdf_free_query_results);
1484 if (!pResults || !librdf_query_results_is_boolean(pResults.get())) {
1485 throw rdf::QueryException(
1486 "librdf_Repository::queryAsk: "
1487 "query result is null or not boolean", *this);
1489 return bool(librdf_query_results_get_boolean(pResults.get()));
1492 // css::rdf::XDocumentRepository:
1493 void SAL_CALL librdf_Repository::setStatementRDFa(
1494 const uno::Reference< rdf::XResource > & i_xSubject,
1495 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
1496 const uno::Reference< rdf::XMetadatable > & i_xObject,
1497 const OUString & i_rRDFaContent,
1498 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
1500 if (!i_xSubject.is()) {
1501 throw lang::IllegalArgumentException(
1502 "librdf_Repository::setStatementRDFa: Subject is null", *this, 0);
1504 if (!i_rPredicates.hasElements()) {
1505 throw lang::IllegalArgumentException(
1506 "librdf_Repository::setStatementRDFa: no Predicates",
1507 *this, 1);
1509 if (std::any_of(i_rPredicates.begin(), i_rPredicates.end(),
1510 [](const uno::Reference< rdf::XURI >& rPredicate) { return !rPredicate.is(); })) {
1511 throw lang::IllegalArgumentException(
1512 "librdf_Repository::setStatementRDFa: Predicate is null", *this, 1);
1514 if (!i_xObject.is()) {
1515 throw lang::IllegalArgumentException(
1516 "librdf_Repository::setStatementRDFa: Object is null", *this, 2);
1518 const uno::Reference<lang::XServiceInfo> xService(i_xObject,
1519 uno::UNO_QUERY_THROW);
1520 uno::Reference<text::XTextRange> xTextRange;
1521 if (xService->supportsService("com.sun.star.table.Cell") ||
1522 xService->supportsService("com.sun.star.text.CellProperties") || // for writer
1523 xService->supportsService("com.sun.star.text.Paragraph"))
1525 xTextRange.set(i_xObject, uno::UNO_QUERY_THROW);
1527 else if (xService->supportsService("com.sun.star.text.Bookmark") ||
1528 xService->supportsService("com.sun.star.text.InContentMetadata"))
1530 const uno::Reference<text::XTextContent> xTextContent(i_xObject,
1531 uno::UNO_QUERY_THROW);
1532 xTextRange = xTextContent->getAnchor();
1534 if (!xTextRange.is()) {
1535 throw lang::IllegalArgumentException(
1536 "librdf_Repository::setStatementRDFa: "
1537 "Object does not support RDFa", *this, 2);
1539 // ensure that the metadatable has an XML ID
1540 i_xObject->ensureMetadataReference();
1541 const beans::StringPair mdref( i_xObject->getMetadataReference() );
1542 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1543 throw uno::RuntimeException(
1544 "librdf_Repository::setStatementRDFa: "
1545 "ensureMetadataReference did not", *this);
1547 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1548 OUString const sContext(s_nsOOo + sXmlId);
1549 OUString const content( (i_rRDFaContent.isEmpty())
1550 ? xTextRange->getString()
1551 : i_rRDFaContent );
1552 uno::Reference<rdf::XNode> xContent;
1553 try {
1554 if (i_xRDFaDatatype.is()) {
1555 xContent.set(rdf::Literal::createWithType(m_xContext,
1556 content, i_xRDFaDatatype),
1557 uno::UNO_QUERY_THROW);
1558 } else {
1559 xContent.set(rdf::Literal::create(m_xContext, content),
1560 uno::UNO_QUERY_THROW);
1562 } catch (const lang::IllegalArgumentException &) {
1563 css::uno::Any anyEx = cppu::getCaughtException();
1564 throw lang::WrappedTargetRuntimeException(
1565 "librdf_Repository::setStatementRDFa: "
1566 "cannot create literal", *this, anyEx);
1569 std::shared_ptr<librdf_TypeConverter::Resource> const pSubject(
1570 librdf_TypeConverter::extractResource_NoLock(i_xSubject));
1571 std::shared_ptr<librdf_TypeConverter::Node> const pContent(
1572 librdf_TypeConverter::extractNode_NoLock(xContent));
1573 ::std::vector< std::shared_ptr<librdf_TypeConverter::Resource> >
1574 predicates;
1575 ::std::transform(i_rPredicates.begin(), i_rPredicates.end(),
1576 ::std::back_inserter(predicates),
1577 [](uno::Reference<rdf::XURI> const& xURI)
1578 { return librdf_TypeConverter::extractResource_NoLock(xURI); });
1580 removeStatementRDFa(i_xObject); // not atomic with insertion?
1582 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1584 if (i_rRDFaContent.isEmpty()) {
1585 m_RDFaXHTMLContentSet.erase(sXmlId);
1586 } else {
1587 m_RDFaXHTMLContentSet.insert(sXmlId);
1591 for (const auto& rPredicatePtr : predicates)
1593 addStatementGraph_Lock(
1594 librdf_TypeConverter::Statement(pSubject,
1595 std::dynamic_pointer_cast<librdf_TypeConverter::URI>(rPredicatePtr),
1596 pContent),
1597 sContext, true);
1600 catch (const container::NoSuchElementException&)
1602 css::uno::Any anyEx = cppu::getCaughtException();
1603 throw lang::WrappedTargetRuntimeException(
1604 "librdf_Repository::setStatementRDFa: "
1605 "cannot addStatementGraph", *this, anyEx);
1609 void SAL_CALL librdf_Repository::removeStatementRDFa(
1610 const uno::Reference< rdf::XMetadatable > & i_xElement)
1612 if (!i_xElement.is()) {
1613 throw lang::IllegalArgumentException(
1614 "librdf_Repository::removeStatementRDFa: Element is null",
1615 *this, 0);
1618 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1619 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1620 return; // nothing to do...
1623 OUString const sXmlId(s_nsOOo + mdref.First + "#" + mdref.Second);
1625 clearGraph_NoLock(sXmlId, true);
1628 beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
1629 librdf_Repository::getStatementRDFa(
1630 const uno::Reference< rdf::XMetadatable > & i_xElement)
1632 if (!i_xElement.is()) {
1633 throw lang::IllegalArgumentException(
1634 "librdf_Repository::getStatementRDFa: Element is null", *this, 0);
1636 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1637 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1638 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >();
1640 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1641 uno::Reference<rdf::XURI> xXmlId;
1642 try {
1643 xXmlId.set( rdf::URI::create(m_xContext, s_nsOOo + sXmlId),
1644 uno::UNO_SET_THROW);
1645 } catch (const lang::IllegalArgumentException &) {
1646 css::uno::Any anyEx = cppu::getCaughtException();
1647 throw lang::WrappedTargetRuntimeException(
1648 "librdf_Repository::getStatementRDFa: "
1649 "cannot create URI for XML ID", *this, anyEx);
1652 ::std::vector< rdf::Statement > ret;
1655 ret = getStatementsGraph_NoLock(nullptr, nullptr, nullptr, xXmlId, true);
1657 catch (const container::NoSuchElementException&)
1659 css::uno::Any anyEx = cppu::getCaughtException();
1660 throw lang::WrappedTargetRuntimeException(
1661 "librdf_Repository::getStatementRDFa: "
1662 "cannot getStatementsGraph", *this, anyEx);
1665 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1667 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
1668 comphelper::containerToSequence(ret), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
1671 extern "C"
1672 librdf_statement *rdfa_context_stream_map_handler(
1673 librdf_stream *i_pStream, void *, librdf_statement *i_pStatement)
1675 OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null");
1676 if (i_pStream) {
1677 librdf_node *pCtxt(
1678 #if LIBRDF_VERSION >= 10012
1679 librdf_stream_get_context2(i_pStream) );
1680 #else
1681 static_cast<librdf_node *>(librdf_stream_get_context(i_pStream)) );
1682 #endif
1683 OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null");
1684 if (pCtxt && isInternalContext(pCtxt)) {
1685 return i_pStatement;
1688 return nullptr;
1691 uno::Reference< container::XEnumeration > SAL_CALL
1692 librdf_Repository::getStatementsRDFa(
1693 const uno::Reference< rdf::XResource > & i_xSubject,
1694 const uno::Reference< rdf::XURI > & i_xPredicate,
1695 const uno::Reference< rdf::XNode > & i_xObject)
1697 if (isMetadatableWithoutMetadata(i_xSubject) ||
1698 isMetadatableWithoutMetadata(i_xPredicate) ||
1699 isMetadatableWithoutMetadata(i_xObject))
1701 return new librdf_GraphResult(this, m_aMutex,
1702 std::shared_ptr<librdf_stream>(),
1703 std::shared_ptr<librdf_node>());
1706 librdf_TypeConverter::Statement const stmt(
1707 librdf_TypeConverter::extractStatement_NoLock(
1708 i_xSubject, i_xPredicate, i_xObject));
1710 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1712 const std::shared_ptr<librdf_statement> pStatement(
1713 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1714 safe_librdf_free_statement);
1715 OSL_ENSURE(pStatement, "mkStatement failed");
1717 const std::shared_ptr<librdf_stream> pStream(
1718 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1719 safe_librdf_free_stream);
1720 if (!pStream) {
1721 throw rdf::RepositoryException(
1722 "librdf_Repository::getStatementsRDFa: "
1723 "librdf_model_find_statements failed", *this);
1726 if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler,
1727 nullptr, nullptr)) {
1728 throw rdf::RepositoryException(
1729 "librdf_Repository::getStatementsRDFa: "
1730 "librdf_stream_add_map failed", *this);
1733 return new librdf_GraphResult(this, m_aMutex, pStream,
1734 std::shared_ptr<librdf_node>());
1737 // css::lang::XInitialization:
1738 void SAL_CALL librdf_Repository::initialize(
1739 const uno::Sequence< css::uno::Any > &)
1741 ::osl::MutexGuard g(m_aMutex);
1743 // m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
1744 m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()),
1745 safe_librdf_free_storage);
1746 m_pModel.reset(m_TypeConverter.createModel_Lock(
1747 m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
1750 NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock(
1751 OUString const& i_rGraphName, bool i_Internal)
1752 // throw (uno::RuntimeException, container::NoSuchElementException,
1753 // rdf::RepositoryException)
1755 ::osl::MutexGuard g(m_aMutex);
1757 return clearGraph_Lock(i_rGraphName, i_Internal);
1760 NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock(
1761 OUString const& i_rGraphName, bool i_Internal)
1763 // internal: must be called with mutex locked!
1764 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) );
1765 if (!i_Internal && iter == m_NamedGraphs.end()) {
1766 throw container::NoSuchElementException(
1767 "librdf_Repository::clearGraph: "
1768 "no graph with given URI exists", *this);
1770 const OString context(
1771 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1773 const std::shared_ptr<librdf_node> pContext(
1774 librdf_new_node_from_uri_string(m_pWorld.get(),
1775 reinterpret_cast<const unsigned char*> (context.getStr())),
1776 safe_librdf_free_node);
1777 if (!pContext) {
1778 throw uno::RuntimeException(
1779 "librdf_Repository::clearGraph: "
1780 "librdf_new_node_from_uri_string failed", *this);
1782 if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get()))
1784 throw rdf::RepositoryException(
1785 "librdf_Repository::clearGraph: "
1786 "librdf_model_context_remove_statements failed", *this);
1788 return iter;
1791 void librdf_Repository::addStatementGraph_NoLock(
1792 const uno::Reference< rdf::XResource > & i_xSubject,
1793 const uno::Reference< rdf::XURI > & i_xPredicate,
1794 const uno::Reference< rdf::XNode > & i_xObject,
1795 const uno::Reference< rdf::XURI > & i_xGraphName)
1796 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1797 // container::NoSuchElementException, rdf::RepositoryException)
1799 if (!i_xSubject.is()) {
1800 throw lang::IllegalArgumentException(
1801 "librdf_Repository::addStatement: Subject is null", *this, 0);
1803 if (!i_xPredicate.is()) {
1804 throw lang::IllegalArgumentException(
1805 "librdf_Repository::addStatement: Predicate is null",
1806 *this, 1);
1808 if (!i_xObject.is()) {
1809 throw lang::IllegalArgumentException(
1810 "librdf_Repository::addStatement: Object is null", *this, 2);
1813 librdf_TypeConverter::Statement const stmt(
1814 librdf_TypeConverter::extractStatement_NoLock(
1815 i_xSubject, i_xPredicate, i_xObject));
1817 const OUString contextU( i_xGraphName->getStringValue() );
1819 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1821 addStatementGraph_Lock(stmt, contextU, false/*i_Internal*/);
1824 void librdf_Repository::addStatementGraph_Lock(
1825 librdf_TypeConverter::Statement const& i_rStatement,
1826 OUString const& i_rGraphName,
1827 bool i_Internal)
1829 if (!i_Internal
1830 && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end()))
1832 throw container::NoSuchElementException(
1833 "librdf_Repository::addStatement: "
1834 "no graph with given URI exists", *this);
1836 const OString context(
1837 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1839 const std::shared_ptr<librdf_node> pContext(
1840 librdf_new_node_from_uri_string(m_pWorld.get(),
1841 reinterpret_cast<const unsigned char*> (context.getStr())),
1842 safe_librdf_free_node);
1843 if (!pContext) {
1844 throw uno::RuntimeException(
1845 "librdf_Repository::addStatement: "
1846 "librdf_new_node_from_uri_string failed", *this);
1848 const std::shared_ptr<librdf_statement> pStatement(
1849 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), i_rStatement),
1850 safe_librdf_free_statement);
1851 OSL_ENSURE(pStatement, "mkStatement failed");
1853 // Test for duplicate statement
1854 // librdf_model_add_statement disallows duplicates while
1855 // librdf_model_context_add_statement allows duplicates
1857 const std::shared_ptr<librdf_stream> pStream(
1858 librdf_model_find_statements_in_context(m_pModel.get(),
1859 pStatement.get(), pContext.get()),
1860 safe_librdf_free_stream);
1861 if (pStream && !librdf_stream_end(pStream.get()))
1862 return;
1865 if (librdf_model_context_add_statement(m_pModel.get(),
1866 pContext.get(), pStatement.get())) {
1867 throw rdf::RepositoryException(
1868 "librdf_Repository::addStatement: "
1869 "librdf_model_context_add_statement failed", *this);
1873 void librdf_Repository::removeStatementsGraph_NoLock(
1874 const uno::Reference< rdf::XResource > & i_xSubject,
1875 const uno::Reference< rdf::XURI > & i_xPredicate,
1876 const uno::Reference< rdf::XNode > & i_xObject,
1877 const uno::Reference< rdf::XURI > & i_xGraphName)
1878 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1879 // container::NoSuchElementException, rdf::RepositoryException)
1881 if (isMetadatableWithoutMetadata(i_xSubject) ||
1882 isMetadatableWithoutMetadata(i_xPredicate) ||
1883 isMetadatableWithoutMetadata(i_xObject))
1885 return;
1888 librdf_TypeConverter::Statement const stmt(
1889 librdf_TypeConverter::extractStatement_NoLock(
1890 i_xSubject, i_xPredicate, i_xObject));
1891 const OUString contextU( i_xGraphName->getStringValue() );
1893 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1895 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1896 throw container::NoSuchElementException(
1897 "librdf_Repository::removeStatements: "
1898 "no graph with given URI exists", *this);
1900 const OString context(
1901 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1903 const std::shared_ptr<librdf_node> pContext(
1904 librdf_new_node_from_uri_string(m_pWorld.get(),
1905 reinterpret_cast<const unsigned char*> (context.getStr())),
1906 safe_librdf_free_node);
1907 if (!pContext) {
1908 throw uno::RuntimeException(
1909 "librdf_Repository::removeStatements: "
1910 "librdf_new_node_from_uri_string failed", *this);
1912 const std::shared_ptr<librdf_statement> pStatement(
1913 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1914 safe_librdf_free_statement);
1915 OSL_ENSURE(pStatement, "mkStatement failed");
1917 const std::shared_ptr<librdf_stream> pStream(
1918 librdf_model_find_statements_in_context(m_pModel.get(),
1919 pStatement.get(), pContext.get()),
1920 safe_librdf_free_stream);
1921 if (!pStream) {
1922 throw rdf::RepositoryException(
1923 "librdf_Repository::removeStatements: "
1924 "librdf_model_find_statements_in_context failed", *this);
1927 if (!librdf_stream_end(pStream.get())) {
1928 do {
1929 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
1930 if (!pStmt) {
1931 throw rdf::RepositoryException(
1932 "librdf_Repository::removeStatements: "
1933 "librdf_stream_get_object failed", *this);
1935 if (librdf_model_context_remove_statement(m_pModel.get(),
1936 pContext.get(), pStmt)) {
1937 throw rdf::RepositoryException(
1938 "librdf_Repository::removeStatements: "
1939 "librdf_model_context_remove_statement failed", *this);
1941 } while (!librdf_stream_next(pStream.get()));
1945 std::vector<rdf::Statement>
1946 librdf_Repository::getStatementsGraph_NoLock(
1947 const uno::Reference< rdf::XResource > & i_xSubject,
1948 const uno::Reference< rdf::XURI > & i_xPredicate,
1949 const uno::Reference< rdf::XNode > & i_xObject,
1950 const uno::Reference< rdf::XURI > & i_xGraphName,
1951 bool i_Internal)
1952 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1953 // container::NoSuchElementException, rdf::RepositoryException)
1955 std::vector<rdf::Statement> ret;
1957 // N.B.: if any of subject, predicate, object is an XMetadatable, and
1958 // has no metadata reference, then there cannot be any node in the graph
1959 // representing it; in order to prevent side effect
1960 // (ensureMetadataReference), check for this condition and return
1961 if (isMetadatableWithoutMetadata(i_xSubject) ||
1962 isMetadatableWithoutMetadata(i_xPredicate) ||
1963 isMetadatableWithoutMetadata(i_xObject))
1965 return ret;
1968 librdf_TypeConverter::Statement const stmt(
1969 librdf_TypeConverter::extractStatement_NoLock(
1970 i_xSubject, i_xPredicate, i_xObject));
1971 const OUString contextU( i_xGraphName->getStringValue() );
1973 ::osl::MutexGuard g(m_aMutex); // don't call i_x* with mutex locked
1975 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1976 throw container::NoSuchElementException(
1977 "librdf_Repository::getStatements: "
1978 "no graph with given URI exists", *this);
1980 const OString context(
1981 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1983 const std::shared_ptr<librdf_node> pContext(
1984 librdf_new_node_from_uri_string(m_pWorld.get(),
1985 reinterpret_cast<const unsigned char*> (context.getStr())),
1986 safe_librdf_free_node);
1987 if (!pContext) {
1988 throw uno::RuntimeException(
1989 "librdf_Repository::getStatements: "
1990 "librdf_new_node_from_uri_string failed", *this);
1992 const std::shared_ptr<librdf_statement> pStatement(
1993 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1994 safe_librdf_free_statement);
1995 OSL_ENSURE(pStatement, "mkStatement failed");
1997 const std::shared_ptr<librdf_stream> pStream(
1998 librdf_model_find_statements_in_context(m_pModel.get(),
1999 pStatement.get(), pContext.get()),
2000 safe_librdf_free_stream);
2001 if (!pStream) {
2002 throw rdf::RepositoryException(
2003 "librdf_Repository::getStatements: "
2004 "librdf_model_find_statements_in_context failed", *this);
2007 librdf_node *pCtxt1(
2008 #if LIBRDF_VERSION >= 10012
2009 librdf_stream_get_context2(pStream.get()) );
2010 #else
2011 static_cast<librdf_node *>(librdf_stream_get_context(pStream.get())) );
2012 #endif
2013 while (!librdf_stream_end(pStream.get()))
2015 auto pCtxt = pCtxt1;
2016 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
2017 if (!pStmt) {
2018 rdf::QueryException e(
2019 "librdf_GraphResult::nextElement: "
2020 "librdf_stream_get_object failed", *this);
2021 throw lang::WrappedTargetException(
2022 "librdf_GraphResult::nextElement: "
2023 "librdf_stream_get_object failed", *this,
2024 uno::makeAny(e));
2026 // NB: pCtxt may be null here if this is result of a graph query
2027 if (pCtxt && isInternalContext(pCtxt)) {
2028 pCtxt = nullptr; // XML ID context is implementation detail!
2031 ret.emplace_back(
2032 getTypeConverter().convertToStatement(pStmt, pCtxt) );
2034 // NB: this will invalidate current item.
2035 librdf_stream_next(pStream.get());
2038 return ret;
2041 extern "C"
2042 void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld)
2044 // fdo#64672 prevent raptor from setting global libxml2 error handlers
2045 raptor_world_set_flag(pRaptorWorld,
2046 RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE, 0);
2047 raptor_world_set_flag(pRaptorWorld,
2048 RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0);
2051 librdf_world *librdf_TypeConverter::createWorld_Lock() const
2053 // create and initialize world
2054 librdf_world *pWorld( librdf_new_world() );
2055 if (!pWorld) {
2056 throw uno::RuntimeException(
2057 "librdf_TypeConverter::createWorld: librdf_new_world failed",
2058 m_rRep);
2060 librdf_world_set_raptor_init_handler(pWorld, nullptr, &librdf_raptor_init);
2061 //FIXME logger, digest, features?
2062 xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs();
2063 librdf_world_open(pWorld);
2064 xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs();
2065 if (newprefs != origprefs) {
2066 // #i110523# restore libxslt global configuration
2067 // (gratuitously overwritten by raptor_init_parser_grddl_common)
2068 // (this is the only reason unordf is linked against libxslt)
2069 xsltSetDefaultSecurityPrefs(origprefs);
2071 return pWorld;
2074 librdf_storage *
2075 librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const
2077 librdf_storage *pStorage(
2078 // librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
2079 librdf_new_storage(i_pWorld, "hashes", nullptr,
2080 "contexts='yes',hash-type='memory'") );
2081 if (!pStorage) {
2082 throw uno::RuntimeException(
2083 "librdf_TypeConverter::createStorage: librdf_new_storage failed",
2084 m_rRep);
2086 return pStorage;
2089 librdf_model *librdf_TypeConverter::createModel_Lock(
2090 librdf_world *i_pWorld, librdf_storage * i_pStorage) const
2092 librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, nullptr) );
2093 if (!pRepository) {
2094 throw uno::RuntimeException(
2095 "librdf_TypeConverter::createModel: librdf_new_model failed",
2096 m_rRep);
2098 //FIXME
2099 #if 0
2101 librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS));
2102 librdf_node * contexts = librdf_model_get_feature(repository, ctxt);
2103 if (!contexts)
2104 throw;
2105 std::cout << "value of contexts feature: ";
2106 prtNode(contexts);
2107 std::cout << std::endl;
2108 // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...);
2109 safe_librdf_free_node(contexts);
2110 safe_librdf_free_uri(ctxt);
2112 #endif
2113 return pRepository;
2116 // this does NOT create a node, only URI
2117 librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld,
2118 OString const& i_rURI)
2120 librdf_uri *pURI( librdf_new_uri(i_pWorld,
2121 reinterpret_cast<const unsigned char *>(i_rURI.getStr())));
2122 if (!pURI) {
2123 throw uno::RuntimeException(
2124 "librdf_TypeConverter::mkURI: librdf_new_uri failed", nullptr);
2126 return pURI;
2129 // extract blank or URI node - call without Mutex locked
2130 std::shared_ptr<librdf_TypeConverter::Resource>
2131 librdf_TypeConverter::extractResource_NoLock(
2132 const uno::Reference< rdf::XResource > & i_xResource)
2134 if (!i_xResource.is()) {
2135 return std::shared_ptr<Resource>();
2137 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2138 if (xBlankNode.is()) {
2139 const OString label(
2140 OUStringToOString(xBlankNode->getStringValue(),
2141 RTL_TEXTENCODING_UTF8) );
2142 return std::shared_ptr<Resource>(new BlankNode(label));
2143 } else { // assumption: everything else is URI
2144 const OString uri(
2145 OUStringToOString(i_xResource->getStringValue(),
2146 RTL_TEXTENCODING_UTF8) );
2147 return std::shared_ptr<Resource>(new URI(uri));
2151 void
2152 librdf_TypeConverter::extractResourceToCacheKey_NoLock(
2153 const uno::Reference< rdf::XResource > & i_xResource, OUStringBuffer& rBuffer)
2155 if (!i_xResource.is()) {
2156 return;
2158 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2159 if (xBlankNode.is()) {
2160 rBuffer.append("BlankNode ").append(xBlankNode->getStringValue());
2161 } else { // assumption: everything else is URI
2162 rBuffer.append("URI ").append(i_xResource->getStringValue());
2166 // create blank or URI node
2167 librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld,
2168 Resource const*const i_pResource)
2170 if (!i_pResource) return nullptr;
2171 BlankNode const*const pBlankNode(
2172 dynamic_cast<BlankNode const*>(i_pResource));
2173 if (pBlankNode) {
2174 librdf_node *pNode(
2175 librdf_new_node_from_blank_identifier(i_pWorld,
2176 reinterpret_cast<const unsigned char*>(
2177 pBlankNode->value.getStr())));
2178 if (!pNode) {
2179 throw uno::RuntimeException(
2180 "librdf_TypeConverter::mkResource: "
2181 "librdf_new_node_from_blank_identifier failed", nullptr);
2183 return pNode;
2184 } else { // assumption: everything else is URI
2185 URI const*const pURI(dynamic_cast<URI const*>(i_pResource));
2186 assert(pURI);
2187 librdf_node *pNode(
2188 librdf_new_node_from_uri_string(i_pWorld,
2189 reinterpret_cast<const unsigned char*>(pURI->value.getStr())));
2190 if (!pNode) {
2191 throw uno::RuntimeException(
2192 "librdf_TypeConverter::mkResource: "
2193 "librdf_new_node_from_uri_string failed", nullptr);
2195 return pNode;
2199 // extract blank or URI or literal node - call without Mutex locked
2200 std::shared_ptr<librdf_TypeConverter::Node>
2201 librdf_TypeConverter::extractNode_NoLock(
2202 const uno::Reference< rdf::XNode > & i_xNode)
2204 if (!i_xNode.is()) {
2205 return std::shared_ptr<Node>();
2207 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2208 if (xResource.is()) {
2209 return extractResource_NoLock(xResource);
2211 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2212 OSL_ENSURE(xLiteral.is(),
2213 "mkNode: someone invented a new rdf.XNode and did not tell me");
2214 if (!xLiteral.is()) {
2215 return std::shared_ptr<Node>();
2217 const OString val(
2218 OUStringToOString(xLiteral->getValue(),
2219 RTL_TEXTENCODING_UTF8) );
2220 const OString lang(
2221 OUStringToOString(xLiteral->getLanguage(),
2222 RTL_TEXTENCODING_UTF8) );
2223 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2224 boost::optional<OString> type;
2225 if (xType.is())
2227 type =
2228 OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8);
2230 return std::shared_ptr<Node>(new Literal(val, lang, type));
2233 // extract blank or URI or literal node - call without Mutex locked
2234 void
2235 librdf_TypeConverter::extractNodeToCacheKey_NoLock(
2236 const uno::Reference< rdf::XNode > & i_xNode,
2237 OUStringBuffer& rBuffer)
2239 if (!i_xNode.is()) {
2240 return;
2242 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2243 if (xResource.is()) {
2244 return extractResourceToCacheKey_NoLock(xResource, rBuffer);
2246 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2247 OSL_ENSURE(xLiteral.is(),
2248 "mkNode: someone invented a new rdf.XNode and did not tell me");
2249 if (!xLiteral.is()) {
2250 return;
2252 rBuffer.append("Literal ").append(xLiteral->getValue()).append("\t").append(xLiteral->getLanguage());
2253 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2254 if (xType.is())
2255 rBuffer.append("\t").append(xType->getStringValue());
2258 // create blank or URI or literal node
2259 librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld,
2260 Node const*const i_pNode)
2262 if (!i_pNode) return nullptr;
2263 Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode));
2264 if (pResource) {
2265 return mkResource_Lock(i_pWorld, pResource);
2268 Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode));
2269 assert(pLiteral);
2270 librdf_node * ret(nullptr);
2271 if (pLiteral->language.isEmpty()) {
2272 if (!pLiteral->type) {
2273 ret = librdf_new_node_from_literal(i_pWorld,
2274 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2275 , nullptr, 0);
2276 } else {
2277 const std::shared_ptr<librdf_uri> pDatatype(
2278 mkURI_Lock(i_pWorld, *pLiteral->type),
2279 safe_librdf_free_uri);
2280 ret = librdf_new_node_from_typed_literal(i_pWorld,
2281 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2282 , nullptr, pDatatype.get());
2284 } else {
2285 if (!pLiteral->type) {
2286 ret = librdf_new_node_from_literal(i_pWorld,
2287 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2288 , pLiteral->language.getStr(), 0);
2289 } else {
2290 OSL_FAIL("mkNode: invalid literal");
2291 return nullptr;
2294 if (!ret) {
2295 throw uno::RuntimeException(
2296 "librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed", nullptr);
2298 return ret;
2301 // extract statement - call without Mutex locked
2302 librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock(
2303 const uno::Reference< rdf::XResource > & i_xSubject,
2304 const uno::Reference< rdf::XURI > & i_xPredicate,
2305 const uno::Reference< rdf::XNode > & i_xObject)
2307 std::shared_ptr<Resource> const pSubject(
2308 extractResource_NoLock(i_xSubject));
2309 std::shared_ptr<URI> const pPredicate(
2310 std::dynamic_pointer_cast<URI>(extractResource_NoLock(i_xPredicate)));
2311 std::shared_ptr<Node> const pObject(extractNode_NoLock(i_xObject));
2312 return Statement(pSubject, pPredicate, pObject);
2315 librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld,
2316 Statement const& i_rStatement)
2318 librdf_node *const pSubject(
2319 mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) );
2320 librdf_node* pPredicate(nullptr);
2321 librdf_node* pObject(nullptr);
2322 try {
2323 pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get());
2324 try {
2325 pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get());
2326 } catch (...) {
2327 safe_librdf_free_node(pPredicate);
2328 throw;
2330 } catch (...) {
2331 safe_librdf_free_node(pSubject);
2332 throw;
2334 // NB: this takes ownership of the nodes! (which is really ugly)
2335 librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld,
2336 pSubject, pPredicate, pObject) );
2337 if (!pStatement) {
2338 throw uno::RuntimeException(
2339 "librdf_TypeConverter::mkStatement: "
2340 "librdf_new_statement_from_nodes failed", nullptr);
2342 return pStatement;
2345 uno::Reference<rdf::XURI>
2346 librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const
2348 if (!i_pURI) return nullptr;
2349 const unsigned char* uri( librdf_uri_as_string(i_pURI) );
2350 if (!uri) {
2351 throw uno::RuntimeException(
2352 "librdf_TypeConverter::convertToXURI: "
2353 "librdf_uri_as_string failed", m_rRep);
2355 OUString uriU( OStringToOUString(
2356 OString(reinterpret_cast<const sal_Char*>(uri)),
2357 RTL_TEXTENCODING_UTF8) );
2358 try {
2359 return rdf::URI::create(m_xContext, uriU);
2360 } catch (const lang::IllegalArgumentException &) {
2361 css::uno::Any anyEx = cppu::getCaughtException();
2362 throw lang::WrappedTargetRuntimeException(
2363 "librdf_TypeConverter::convertToXURI: "
2364 "illegal uri", m_rRep, anyEx);
2368 uno::Reference<rdf::XURI>
2369 librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const
2371 if (!i_pNode) return nullptr;
2372 if (librdf_node_is_resource(i_pNode)) {
2373 librdf_uri* pURI( librdf_node_get_uri(i_pNode) );
2374 if (!pURI) {
2375 throw uno::RuntimeException(
2376 "librdf_TypeConverter::convertToXURI: "
2377 "resource has no uri", m_rRep);
2379 return convertToXURI(pURI);
2380 } else {
2381 OSL_FAIL("convertToXURI: unknown librdf_node");
2382 return nullptr;
2386 uno::Reference<rdf::XResource>
2387 librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const
2389 if (!i_pNode) return nullptr;
2390 if (librdf_node_is_blank(i_pNode)) {
2391 const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) );
2392 if (!label) {
2393 throw uno::RuntimeException(
2394 "librdf_TypeConverter::convertToXResource: "
2395 "blank node has no label", m_rRep);
2397 OUString labelU( OStringToOUString(
2398 OString(reinterpret_cast<const sal_Char*>(label)),
2399 RTL_TEXTENCODING_UTF8) );
2400 try {
2401 return rdf::BlankNode::create(m_xContext, labelU);
2402 } catch (const lang::IllegalArgumentException &) {
2403 css::uno::Any anyEx = cppu::getCaughtException();
2404 throw lang::WrappedTargetRuntimeException(
2405 "librdf_TypeConverter::convertToXResource: "
2406 "illegal blank node label", m_rRep, anyEx);
2408 } else {
2409 return convertToXURI(i_pNode);
2413 uno::Reference<rdf::XNode>
2414 librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const
2416 if (!i_pNode) return nullptr;
2417 if (!librdf_node_is_literal(i_pNode)) {
2418 return convertToXResource(i_pNode);
2420 const unsigned char* value( librdf_node_get_literal_value(i_pNode) );
2421 if (!value) {
2422 throw uno::RuntimeException(
2423 "librdf_TypeConverter::convertToXNode: "
2424 "literal has no value", m_rRep);
2426 const char * lang( librdf_node_get_literal_value_language(i_pNode) );
2427 librdf_uri* pType(
2428 librdf_node_get_literal_value_datatype_uri(i_pNode) );
2429 OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal");
2430 const OUString valueU( OStringToOUString(
2431 OString(reinterpret_cast<const sal_Char*>(value)),
2432 RTL_TEXTENCODING_UTF8) );
2433 if (lang) {
2434 const OUString langU( OStringToOUString(
2435 OString(reinterpret_cast<const sal_Char*>(lang)),
2436 RTL_TEXTENCODING_UTF8) );
2437 return rdf::Literal::createWithLanguage(m_xContext, valueU, langU);
2438 } else if (pType) {
2439 uno::Reference<rdf::XURI> xType(convertToXURI(pType));
2440 OSL_ENSURE(xType.is(), "convertToXNode: null uri");
2441 return rdf::Literal::createWithType(m_xContext, valueU, xType);
2442 } else {
2443 return rdf::Literal::create(m_xContext, valueU);
2447 rdf::Statement
2448 librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt,
2449 librdf_node* i_pContext) const
2451 if (!i_pStmt) {
2452 throw uno::RuntimeException();
2454 return rdf::Statement(
2455 convertToXResource(librdf_statement_get_subject(i_pStmt)),
2456 convertToXURI(librdf_statement_get_predicate(i_pStmt)),
2457 convertToXNode(librdf_statement_get_object(i_pStmt)),
2458 convertToXURI(i_pContext));
2461 } // closing anonymous implementation namespace
2464 // component helper namespace
2465 namespace comp_librdf_Repository {
2467 OUString _getImplementationName() {
2468 return "librdf_Repository";
2471 uno::Sequence< OUString > _getSupportedServiceNames()
2473 uno::Sequence< OUString > s { "com.sun.star.rdf.Repository" };
2474 return s;
2477 uno::Reference< uno::XInterface > _create(
2478 const uno::Reference< uno::XComponentContext > & context)
2480 return static_cast< ::cppu::OWeakObject * >(new librdf_Repository(context));
2483 } // closing component helper namespace
2485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */