LibreOffice Module unoxml (master) 1
librdf_repository.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <string.h>
21
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>
30
31#include <optional>
32
33#include <libxslt/security.h>
34
35#include <redland.h>
36
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>
54
55#include <rtl/ref.hxx>
56#include <rtl/ustrbuf.hxx>
57#include <rtl/ustring.hxx>
58#include <osl/diagnose.h>
63
66
67#include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
68#include <utility>
69
85namespace {
86
87class librdf_NamedGraph;
88class librdf_Repository;
89
90using namespace ::com::sun::star;
91
92typedef std::map< OUString, ::rtl::Reference<librdf_NamedGraph> >
93 NamedGraphMap_t;
94
95const char s_sparql [] = "sparql";
96const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/";
97
98
99//FIXME: this approach is not ideal. can we use blank nodes instead?
100bool isInternalContext(librdf_node *i_pNode) noexcept
101{
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;
115 }
116 }
117 return false;
118 }
119 return true;
120}
121
122
123// n.b.: librdf destructor functions dereference null pointers!
124// so they need to be wrapped to be usable with std::shared_ptr.
125void safe_librdf_free_world(librdf_world *const world)
126{
127 if (world) { librdf_free_world(world); }
128}
129void safe_librdf_free_model(librdf_model *const model)
130{
131 if (model) { librdf_free_model(model); }
132}
133void safe_librdf_free_node(librdf_node* node)
134{
135 if (node) { librdf_free_node(node); }
136}
137void safe_librdf_free_parser(librdf_parser *const parser)
138{
139 if (parser) { librdf_free_parser(parser); }
140}
141void safe_librdf_free_query(librdf_query *const query)
142{
143 if (query) { librdf_free_query(query); }
144}
145void
146safe_librdf_free_query_results(librdf_query_results *const query_results)
147{
148 if (query_results) { librdf_free_query_results(query_results); }
149}
150void safe_librdf_free_serializer(librdf_serializer *const serializer)
151{
152 if (serializer) { librdf_free_serializer(serializer); }
153}
154void safe_librdf_free_statement(librdf_statement *const statement)
155{
156 if (statement) { librdf_free_statement(statement); }
157}
158void safe_librdf_free_storage(librdf_storage *const storage)
159{
160 if (storage) { librdf_free_storage(storage); }
161}
162void safe_librdf_free_stream(librdf_stream *const stream)
163{
164 if (stream) { librdf_free_stream(stream); }
165}
166void safe_librdf_free_uri(librdf_uri *const uri)
167{
168 if (uri) { librdf_free_uri(uri); }
169}
170
171
174class librdf_TypeConverter
175{
176public:
177
178 // some wrapper classes to temporarily hold values of UNO XNodes
179 struct Node
180 {
181 virtual ~Node() {}
182 };
183 struct Resource : public Node { };
184 struct URI : public Resource
185 {
186 OString const value;
187 explicit URI(OString i_Value)
188 : value(std::move(i_Value))
189 { }
190 };
191 struct BlankNode : public Resource
192 {
193 OString const value;
194 explicit BlankNode(OString i_Value)
195 : value(std::move(i_Value))
196 { }
197 };
198 struct Literal : public Node
199 {
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))
208 { }
209 };
210 struct Statement
211 {
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))
221 { }
222 };
223
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 { };
230
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;
265
266private:
267 uno::Reference< uno::XComponentContext > const m_xContext;
268 librdf_Repository & m_rRep;
269};
270
271
274class librdf_Repository:
275// private ::cppu::BaseMutex,
276 public ::cppu::WeakImplHelper<
277 lang::XServiceInfo,
278 rdf::XDocumentRepository,
279 lang::XInitialization>
280{
281public:
282
283 explicit librdf_Repository(
284 uno::Reference< uno::XComponentContext > const & i_xContext);
285 virtual ~librdf_Repository() override;
286
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;
293
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;
322
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;
339
340 // css::lang::XInitialization:
341 virtual void SAL_CALL initialize(
342 const uno::Sequence< css::uno::Any > & i_rArguments) override;
343
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);
377
378 const librdf_TypeConverter& getTypeConverter() const { return m_TypeConverter; };
379
380private:
381
382 librdf_Repository(librdf_Repository const&) = delete;
383 librdf_Repository& operator=(librdf_Repository const&) = delete;
384
386 uno::Reference< uno::XComponentContext > const m_xContext;
387
389
399 static std::shared_ptr<librdf_world> m_pWorld;
401 static sal_uInt32 m_NumInstances;
403 static std::mutex m_aMutex;
404
405 // NB: sequence of the shared pointers is important!
407 std::shared_ptr<librdf_storage> m_pStorage;
409 std::shared_ptr<librdf_model> m_pModel;
410
412 NamedGraphMap_t m_NamedGraphs;
413
415 librdf_TypeConverter m_TypeConverter;
416
418 ::std::set< OUString > m_RDFaXHTMLContentSet;
419};
420
421
425class librdf_GraphResult:
426 public ::cppu::WeakImplHelper<
427 container::XEnumeration>
428{
429public:
430
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 { };
443
444 virtual ~librdf_GraphResult() override
445 {
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();
450 }
451
452 // css::container::XEnumeration:
453 virtual sal_Bool SAL_CALL hasMoreElements() override;
454 virtual uno::Any SAL_CALL nextElement() override;
455
456private:
457
458 librdf_GraphResult(librdf_GraphResult const&) = delete;
459 librdf_GraphResult& operator=(librdf_GraphResult const&) = delete;
460
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.
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;
473
474 librdf_node* getContext_Lock() const;
475};
476
477
478// css::container::XEnumeration:
479sal_Bool SAL_CALL
480librdf_GraphResult::hasMoreElements()
481{
482 std::scoped_lock g(m_rMutex);
483 return m_pStream && !librdf_stream_end(m_pStream.get());
484}
485
486librdf_node* librdf_GraphResult::getContext_Lock() const
487{
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();
499}
500
501css::uno::Any SAL_CALL
502librdf_GraphResult::nextElement()
503{
504 std::scoped_lock g(m_rMutex);
505 if (m_pStream && librdf_stream_end(m_pStream.get())) {
506 throw container::NoSuchElementException();
507 }
508 librdf_node * pCtxt = getContext_Lock();
509
510 librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) );
511 if (!pStmt) {
512 rdf::QueryException e(
513 "librdf_GraphResult::nextElement: "
514 "librdf_stream_get_object failed", *this);
515 throw lang::WrappedTargetException(
516 "librdf_GraphResult::nextElement: "
517 "librdf_stream_get_object failed", *this,
518 uno::Any(e));
519 }
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!
523 }
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);
529}
530
531
535class librdf_GraphResult2:
536 public ::cppu::WeakImplHelper<
537 container::XEnumeration>
538{
539public:
540
541 librdf_GraphResult2(std::vector<rdf::Statement> statements)
542 : m_vStatements(std::move(statements))
543 { };
544
545 // css::container::XEnumeration:
546 virtual sal_Bool SAL_CALL hasMoreElements() override;
547 virtual uno::Any SAL_CALL nextElement() override;
548
549private:
550
551 std::vector<rdf::Statement> m_vStatements;
552 std::atomic<std::size_t> m_nIndex = 0;
553};
554
555
556// css::container::XEnumeration:
557sal_Bool SAL_CALL
558librdf_GraphResult2::hasMoreElements()
559{
560 return m_nIndex < m_vStatements.size();
561}
562
563css::uno::Any SAL_CALL
564librdf_GraphResult2::nextElement()
565{
566 std::size_t const n = m_nIndex++;
567 if (m_vStatements.size() <= n)
568 {
569 m_nIndex = m_vStatements.size(); // avoid overflow
570 throw container::NoSuchElementException();
571 }
572 return uno::Any(m_vStatements[n]);
573}
574
577class librdf_QuerySelectResult:
578 public ::cppu::WeakImplHelper<
579 rdf::XQuerySelectResult>
580{
581public:
582
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 { };
594
595 virtual ~librdf_QuerySelectResult() override
596 {
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();
601 }
602
603 // css::container::XEnumeration:
604 virtual sal_Bool SAL_CALL hasMoreElements() override;
605 virtual uno::Any SAL_CALL nextElement() override;
606
607 // css::rdf::XQuerySelectResult:
608 virtual uno::Sequence< OUString > SAL_CALL getBindingNames() override;
609
610private:
611
612 librdf_QuerySelectResult(librdf_QuerySelectResult const&) = delete;
613 librdf_QuerySelectResult& operator=(librdf_QuerySelectResult const&) = delete;
614
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.
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;
626};
627
628
629// css::container::XEnumeration:
630sal_Bool SAL_CALL
631librdf_QuerySelectResult::hasMoreElements()
632{
633 std::scoped_lock g(m_rMutex);
634 return !librdf_query_results_finished(m_pQueryResult.get());
635}
636
637class NodeArray : private std::vector<librdf_node*>
638{
639public:
640 NodeArray(int cnt) : std::vector<librdf_node*>(cnt) {}
641
642 ~NodeArray() noexcept
643 {
644 std::for_each(begin(), end(), safe_librdf_free_node);
645 }
646
647 using std::vector<librdf_node*>::data;
648 using std::vector<librdf_node*>::operator[];
649};
650
651css::uno::Any SAL_CALL
652librdf_QuerySelectResult::nextElement()
653{
654 std::scoped_lock g(m_rMutex);
655 if (librdf_query_results_finished(m_pQueryResult.get())) {
656 throw container::NoSuchElementException();
657 }
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()))
663 {
664 rdf::QueryException e(
665 "librdf_QuerySelectResult::nextElement: "
666 "librdf_query_results_get_bindings failed", *this);
667 throw lang::WrappedTargetException(
668 "librdf_QuerySelectResult::nextElement: "
669 "librdf_query_results_get_bindings failed", *this,
670 uno::Any(e));
671 }
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]);
676 }
677 // NB: this will invalidate current item.
678 librdf_query_results_next(m_pQueryResult.get());
679 return uno::Any(ret);
680}
681
682// css::rdf::XQuerySelectResult:
683uno::Sequence< OUString > SAL_CALL
684librdf_QuerySelectResult::getBindingNames()
685{
686 // const - no lock needed
687 return m_BindingNames;
688}
689
690
693class librdf_NamedGraph:
694 public ::cppu::WeakImplHelper<
695 rdf::XNamedGraph>
696{
697public:
698 librdf_NamedGraph(librdf_Repository * i_pRep,
699 uno::Reference<rdf::XURI> i_xName)
700 : m_wRep(i_pRep)
701 , m_pRep(i_pRep)
702 , m_xName(std::move(i_xName))
703 { };
704
705 // css::rdf::XNode:
706 virtual OUString SAL_CALL getStringValue() override;
707
708 // css::rdf::XURI:
709 virtual OUString SAL_CALL getNamespace() override;
710 virtual OUString SAL_CALL getLocalName() override;
711
712 // css::rdf::XNamedGraph:
713 virtual uno::Reference<rdf::XURI> SAL_CALL getName() override;
714 virtual void SAL_CALL clear() override;
715 virtual void SAL_CALL addStatement(
716 const uno::Reference< rdf::XResource > & i_xSubject,
717 const uno::Reference< rdf::XURI > & i_xPredicate,
718 const uno::Reference< rdf::XNode > & i_xObject) override;
719 virtual void SAL_CALL removeStatements(
720 const uno::Reference< rdf::XResource > & i_xSubject,
721 const uno::Reference< rdf::XURI > & i_xPredicate,
722 const uno::Reference< rdf::XNode > & i_xObject) override;
723 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
724 const uno::Reference< rdf::XResource > & i_xSubject,
725 const uno::Reference< rdf::XURI > & i_xPredicate,
726 const uno::Reference< rdf::XNode > & i_xObject) override;
727
728private:
729
730 librdf_NamedGraph(librdf_NamedGraph const&) = delete;
731 librdf_NamedGraph& operator=(librdf_NamedGraph const&) = delete;
732
733 static OUString createCacheKey_NoLock(
734 const uno::Reference< rdf::XResource > & i_xSubject,
735 const uno::Reference< rdf::XURI > & i_xPredicate,
736 const uno::Reference< rdf::XNode > & i_xObject);
737
739 uno::WeakReference< rdf::XRepository > const m_wRep;
740 librdf_Repository *const m_pRep;
741 uno::Reference< rdf::XURI > const m_xName;
742
744 std::map<OUString, std::vector<rdf::Statement>> m_aStatementsCache;
745 std::mutex m_CacheMutex;
746};
747
748
749// css::rdf::XNode:
750OUString SAL_CALL librdf_NamedGraph::getStringValue()
751{
752 return m_xName->getStringValue();
753}
754
755// css::rdf::XURI:
756OUString SAL_CALL librdf_NamedGraph::getNamespace()
757{
758 return m_xName->getNamespace();
759}
760
761OUString SAL_CALL librdf_NamedGraph::getLocalName()
762{
763 return m_xName->getLocalName();
764}
765
766// css::rdf::XNamedGraph:
767uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName()
768{
769 return m_xName;
770}
771
772void SAL_CALL librdf_NamedGraph::clear()
773{
774 uno::Reference< rdf::XRepository > xRep( m_wRep );
775 if (!xRep.is()) {
776 throw rdf::RepositoryException(
777 "librdf_NamedGraph::clear: repository is gone", *this);
778 }
779 const OUString contextU( m_xName->getStringValue() );
780 try {
781 m_pRep->clearGraph_NoLock(contextU);
782 } catch (lang::IllegalArgumentException & ex) {
783 css::uno::Any anyEx = cppu::getCaughtException();
784 throw lang::WrappedTargetRuntimeException( ex.Message,
785 *this, anyEx );
786 }
787 std::unique_lock g(m_CacheMutex);
788 m_aStatementsCache.clear();
789}
790
791void SAL_CALL librdf_NamedGraph::addStatement(
792 const uno::Reference< rdf::XResource > & i_xSubject,
793 const uno::Reference< rdf::XURI > & i_xPredicate,
794 const uno::Reference< rdf::XNode > & i_xObject)
795{
796 uno::Reference< rdf::XRepository > xRep( m_wRep );
797 if (!xRep.is()) {
798 throw rdf::RepositoryException(
799 "librdf_NamedGraph::addStatement: repository is gone", *this);
800 }
801 {
802 std::unique_lock g(m_CacheMutex);
803 m_aStatementsCache.clear();
804 }
805 m_pRep->addStatementGraph_NoLock(
806 i_xSubject, i_xPredicate, i_xObject, m_xName);
807}
808
809void SAL_CALL librdf_NamedGraph::removeStatements(
810 const uno::Reference< rdf::XResource > & i_xSubject,
811 const uno::Reference< rdf::XURI > & i_xPredicate,
812 const uno::Reference< rdf::XNode > & i_xObject)
813{
814 uno::Reference< rdf::XRepository > xRep( m_wRep );
815 if (!xRep.is()) {
816 throw rdf::RepositoryException(
817 "librdf_NamedGraph::removeStatements: repository is gone", *this);
818 }
819 {
820 std::unique_lock g(m_CacheMutex);
821 m_aStatementsCache.clear();
822 }
823 m_pRep->removeStatementsGraph_NoLock(
824 i_xSubject, i_xPredicate, i_xObject, m_xName);
825}
826
827OUString librdf_NamedGraph::createCacheKey_NoLock(
828 const uno::Reference< rdf::XResource > & i_xSubject,
829 const uno::Reference< rdf::XURI > & i_xPredicate,
830 const uno::Reference< rdf::XNode > & i_xObject)
831{
832 OUStringBuffer cacheKey(256);
833 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xSubject, cacheKey);
834 cacheKey.append("\t");
835 librdf_TypeConverter::extractResourceToCacheKey_NoLock(i_xPredicate, cacheKey);
836 cacheKey.append("\t");
837 librdf_TypeConverter::extractNodeToCacheKey_NoLock(i_xObject, cacheKey);
838 return cacheKey.makeStringAndClear();
839}
840
841uno::Reference< container::XEnumeration > SAL_CALL
842librdf_NamedGraph::getStatements(
843 const uno::Reference< rdf::XResource > & i_xSubject,
844 const uno::Reference< rdf::XURI > & i_xPredicate,
845 const uno::Reference< rdf::XNode > & i_xObject)
846{
847 OUString cacheKey = createCacheKey_NoLock(i_xSubject, i_xPredicate, i_xObject);
848 {
849 std::unique_lock g(m_CacheMutex);
850 auto it = m_aStatementsCache.find(cacheKey);
851 if (it != m_aStatementsCache.end()) {
852 return new librdf_GraphResult2(it->second);
853 }
854 }
855
856 uno::Reference< rdf::XRepository > xRep( m_wRep );
857 if (!xRep.is()) {
858 throw rdf::RepositoryException(
859 "librdf_NamedGraph::getStatements: repository is gone", *this);
860 }
861 std::vector<rdf::Statement> vStatements = m_pRep->getStatementsGraph_NoLock(
862 i_xSubject, i_xPredicate, i_xObject, m_xName);
863
864 {
865 std::unique_lock g(m_CacheMutex);
866 m_aStatementsCache.emplace(cacheKey, vStatements);
867 }
868 return new librdf_GraphResult2(std::move(vStatements));
869}
870
871
872std::shared_ptr<librdf_world> librdf_Repository::m_pWorld;
873sal_uInt32 librdf_Repository::m_NumInstances = 0;
874std::mutex librdf_Repository::m_aMutex;
875
876librdf_Repository::librdf_Repository(
877 uno::Reference< uno::XComponentContext > const & i_xContext)
878 : /*BaseMutex(),*/ m_xContext(i_xContext)
879// m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ),
880 , m_pStorage(static_cast<librdf_storage*>(nullptr), safe_librdf_free_storage)
881 , m_pModel (static_cast<librdf_model *>(nullptr), safe_librdf_free_model )
882 , m_TypeConverter(i_xContext, *this)
883{
884 OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context");
885
886 std::scoped_lock g(m_aMutex);
887 if (!m_NumInstances++) {
888 m_pWorld.reset(m_TypeConverter.createWorld_Lock(),
889 safe_librdf_free_world);
890 }
891}
892
893librdf_Repository::~librdf_Repository()
894{
895 std::scoped_lock g(m_aMutex);
896
897 // must destroy these before world!
898 m_pModel.reset();
899 m_pStorage.reset();
900
901 // FIXME: so it turns out that calling librdf_free_world will
902 // (via raptor_sax2_finish) call xmlCleanupParser, which will
903 // free libxml2's globals! ARRRGH!!! => never call librdf_free_world
904#if 0
905 if (!--m_NumInstances) {
906 m_pWorld.reset();
907 }
908#endif
909}
910
911// com.sun.star.uno.XServiceInfo:
912OUString SAL_CALL librdf_Repository::getImplementationName()
913{
914 return "librdf_Repository";
915}
916
917sal_Bool SAL_CALL librdf_Repository::supportsService(
918 OUString const & serviceName)
919{
920 return cppu::supportsService(this, serviceName);
921}
922
923uno::Sequence< OUString > SAL_CALL
924librdf_Repository::getSupportedServiceNames()
925{
926 return { "com.sun.star.rdf.Repository" };
927}
928
929// css::rdf::XRepository:
930uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode()
931{
932 std::scoped_lock g(m_aMutex);
933 const std::shared_ptr<librdf_node> pNode(
934 librdf_new_node_from_blank_identifier(m_pWorld.get(), nullptr),
935 safe_librdf_free_node);
936 if (!pNode) {
937 throw uno::RuntimeException(
938 "librdf_Repository::createBlankNode: "
939 "librdf_new_node_from_blank_identifier failed", *this);
940 }
941 const unsigned char * id (librdf_node_get_blank_identifier(pNode.get()));
942 if (!id) {
943 throw uno::RuntimeException(
944 "librdf_Repository::createBlankNode: "
945 "librdf_node_get_blank_identifier failed", *this);
946 }
947 const OUString nodeID(OUString::createFromAscii(
948 reinterpret_cast<const char *>(id)));
949 try {
950 return rdf::BlankNode::create(m_xContext, nodeID);
951 } catch (const lang::IllegalArgumentException &) {
952 css::uno::Any anyEx = cppu::getCaughtException();
953 throw lang::WrappedTargetRuntimeException(
954 "librdf_Repository::createBlankNode: "
955 "illegal blank node label", *this, anyEx);
956 }
957}
958
959//void SAL_CALL
960uno::Reference<rdf::XNamedGraph> SAL_CALL
961librdf_Repository::importGraph(::sal_Int16 i_Format,
962 const uno::Reference< io::XInputStream > & i_xInStream,
963 const uno::Reference< rdf::XURI > & i_xGraphName,
964 const uno::Reference< rdf::XURI > & i_xBaseURI)
965{
966 if (!i_xInStream.is()) {
967 throw lang::IllegalArgumentException(
968 "librdf_Repository::importGraph: stream is null", *this, 1);
969 }
970 //FIXME: other formats
971 if (i_Format != rdf::FileFormat::RDF_XML) {
972 throw datatransfer::UnsupportedFlavorException(
973 "librdf_Repository::importGraph: file format not supported", *this);
974 }
975 if (!i_xGraphName.is()) {
976 throw lang::IllegalArgumentException(
977 "librdf_Repository::importGraph: graph name is null", *this, 2);
978 }
979 if (i_xGraphName->getStringValue().startsWith(s_nsOOo))
980 {
981 throw lang::IllegalArgumentException(
982 "librdf_Repository::importGraph: URI is reserved", *this, 0);
983 }
984 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
985 throw lang::IllegalArgumentException(
986 "librdf_Repository::importGraph: base URI is null", *this, 3);
987 }
988 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
989 const OUString baseURIU( i_xBaseURI->getStringValue() );
990 if (baseURIU.indexOf('#') >= 0) {
991 throw lang::IllegalArgumentException(
992 "librdf_Repository::importGraph: base URI is not absolute", *this, 3);
993 }
994
995 const OUString contextU( i_xGraphName->getStringValue() );
996
997 uno::Sequence<sal_Int8> buf;
998 uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
999 // UGLY: if only redland could read streams...
1000 const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
1001 // exceptions are propagated
1002 i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
1003
1004 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1005
1006 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1007 throw container::ElementExistException(
1008 "librdf_Repository::importGraph: graph with given URI exists", *this);
1009 }
1010 const OString context(
1011 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1012
1013 const std::shared_ptr<librdf_node> pContext(
1014 librdf_new_node_from_uri_string(m_pWorld.get(),
1015 reinterpret_cast<const unsigned char*> (context.getStr())),
1016 safe_librdf_free_node);
1017 if (!pContext) {
1018 throw uno::RuntimeException(
1019 "librdf_Repository::importGraph: librdf_new_node_from_uri_string failed", *this);
1020 }
1021
1022 const OString baseURI(
1023 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1024 const std::shared_ptr<librdf_uri> pBaseURI(
1025 librdf_new_uri(m_pWorld.get(),
1026 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1027 safe_librdf_free_uri);
1028 if (!pBaseURI) {
1029 throw uno::RuntimeException( "librdf_Repository::importGraph: librdf_new_uri failed", *this);
1030 }
1031
1032 const std::shared_ptr<librdf_parser> pParser(
1033 librdf_new_parser(m_pWorld.get(), "rdfxml", nullptr, nullptr),
1034 safe_librdf_free_parser);
1035 if (!pParser) {
1036 throw uno::RuntimeException(
1037 "librdf_Repository::importGraph: "
1038 "librdf_new_parser failed", *this);
1039 }
1040
1041 const std::shared_ptr<librdf_stream> pStream(
1042 librdf_parser_parse_counted_string_as_stream(pParser.get(),
1043 reinterpret_cast<const unsigned char*>(buf.getConstArray()),
1044 buf.getLength(), pBaseURI.get()),
1045 safe_librdf_free_stream);
1046 if (!pStream) {
1047 throw rdf::ParseException(
1048 "librdf_Repository::importGraph: "
1049 "librdf_parser_parse_counted_string_as_stream failed", *this);
1050 }
1052 new librdf_NamedGraph(this, i_xGraphName));
1053 m_NamedGraphs.insert(std::make_pair(contextU, pGraph));
1054 if (librdf_model_context_add_statements(m_pModel.get(),
1055 pContext.get(), pStream.get())) {
1056 throw rdf::RepositoryException(
1057 "librdf_Repository::importGraph: "
1058 "librdf_model_context_add_statements failed", *this);
1059 }
1060
1061 return pGraph;
1062}
1063
1064void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
1065{
1066 if (!length)
1067 return;
1068
1069 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream,
1070 uno::UNO_QUERY);
1071
1072 bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData();
1073
1074 // exceptions are propagated
1075 if (!bAddChaff)
1076 {
1077 const uno::Sequence<sal_Int8> buf(
1078 reinterpret_cast<sal_Int8*>(pBuffer), length);
1079 rStream->writeBytes(buf);
1080 }
1081 else
1082 {
1083 unsigned char *postcomment =
1084 reinterpret_cast<unsigned char*>(strchr(reinterpret_cast<char*>(pBuffer), '\n'));
1085 if (postcomment != nullptr)
1086 {
1087 ++postcomment;
1088
1089 size_t preamblelen = postcomment - pBuffer;
1090
1091 uno::Sequence<sal_Int8> buf(
1092 reinterpret_cast<sal_Int8*>(pBuffer), preamblelen);
1093 rStream->writeBytes(buf);
1094
1095 OString aComment =
1096 "<!--" +
1098 "-->";
1099
1100 buf = uno::Sequence<sal_Int8>(
1101 reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength());
1102 rStream->writeBytes(buf);
1103
1104 buf = uno::Sequence<sal_Int8>(
1105 reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen);
1106 rStream->writeBytes(buf);
1107 }
1108 }
1109}
1110
1111void SAL_CALL
1112librdf_Repository::exportGraph(::sal_Int16 i_Format,
1113 const uno::Reference< io::XOutputStream > & i_xOutStream,
1114 const uno::Reference< rdf::XURI > & i_xGraphName,
1115 const uno::Reference< rdf::XURI > & i_xBaseURI)
1116{
1117 if (!i_xOutStream.is()) {
1118 throw lang::IllegalArgumentException(
1119 "librdf_Repository::exportGraph: stream is null", *this, 1);
1120 }
1121 // FIXME: other formats
1122 if (i_Format != rdf::FileFormat::RDF_XML) {
1123 throw datatransfer::UnsupportedFlavorException(
1124 "librdf_Repository::exportGraph: "
1125 "file format not supported", *this);
1126 }
1127 if (!i_xGraphName.is()) {
1128 throw lang::IllegalArgumentException(
1129 "librdf_Repository::exportGraph: "
1130 "graph name is null", *this, 2);
1131 }
1132 if (!i_xBaseURI.is()) { //FIXME: any i_Format that don't need a base URI?
1133 throw lang::IllegalArgumentException(
1134 "librdf_Repository::exportGraph: "
1135 "base URI is null", *this, 3);
1136 }
1137 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
1138 const OUString baseURIU( i_xBaseURI->getStringValue() );
1139 if (baseURIU.indexOf('#') >= 0) {
1140 throw lang::IllegalArgumentException(
1141 "librdf_Repository::exportGraph: "
1142 "base URI is not absolute", *this, 3);
1143 }
1144
1145 const OUString contextU( i_xGraphName->getStringValue() );
1146
1147 std::unique_lock g(m_aMutex); // don't call i_x* with mutex locked
1148
1149 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1150 throw container::NoSuchElementException(
1151 "librdf_Repository::exportGraph: "
1152 "no graph with given URI exists", *this);
1153 }
1154 const OString context(
1155 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1156
1157 const std::shared_ptr<librdf_node> pContext(
1158 librdf_new_node_from_uri_string(m_pWorld.get(),
1159 reinterpret_cast<const unsigned char*> (context.getStr())),
1160 safe_librdf_free_node);
1161 if (!pContext) {
1162 throw uno::RuntimeException(
1163 "librdf_Repository::exportGraph: "
1164 "librdf_new_node_from_uri_string failed", *this);
1165 }
1166 const OString baseURI(
1167 OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1168 const std::shared_ptr<librdf_uri> pBaseURI(
1169 librdf_new_uri(m_pWorld.get(),
1170 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1171 safe_librdf_free_uri);
1172 if (!pBaseURI) {
1173 throw uno::RuntimeException(
1174 "librdf_Repository::exportGraph: "
1175 "librdf_new_uri failed", *this);
1176 }
1177
1178 const std::shared_ptr<librdf_stream> pStream(
1179 librdf_model_context_as_stream(m_pModel.get(), pContext.get()),
1180 safe_librdf_free_stream);
1181 if (!pStream) {
1182 throw rdf::RepositoryException(
1183 "librdf_Repository::exportGraph: "
1184 "librdf_model_context_as_stream failed", *this);
1185 }
1186 const char * const format("rdfxml");
1187 // #i116443#: abbrev breaks when certain URIs are used as data types
1188// const char *format("rdfxml-abbrev");
1189 const std::shared_ptr<librdf_serializer> pSerializer(
1190 librdf_new_serializer(m_pWorld.get(), format, nullptr, nullptr),
1191 safe_librdf_free_serializer);
1192 if (!pSerializer) {
1193 throw uno::RuntimeException(
1194 "librdf_Repository::exportGraph: "
1195 "librdf_new_serializer failed", *this);
1196 }
1197
1198 const std::shared_ptr<librdf_uri> pRelativeURI(
1199 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1200 ("http://feature.librdf.org/raptor-relativeURIs")),
1201 safe_librdf_free_uri);
1202 const std::shared_ptr<librdf_uri> pWriteBaseURI(
1203 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1204 ("http://feature.librdf.org/raptor-writeBaseURI")),
1205 safe_librdf_free_uri);
1206 const std::shared_ptr<librdf_node> p0(
1207 librdf_new_node_from_literal(m_pWorld.get(),
1208 reinterpret_cast<const unsigned char*> ("0"), nullptr, 0),
1209 safe_librdf_free_node);
1210 const std::shared_ptr<librdf_node> p1(
1211 librdf_new_node_from_literal(m_pWorld.get(),
1212 reinterpret_cast<const unsigned char*> ("1"), nullptr, 0),
1213 safe_librdf_free_node);
1214 if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) {
1215 throw uno::RuntimeException(
1216 "librdf_Repository::exportGraph: "
1217 "librdf_new_uri or librdf_new_node_from_literal failed", *this);
1218 }
1219
1220 // make URIs relative to base URI
1221 if (librdf_serializer_set_feature(pSerializer.get(),
1222 pRelativeURI.get(), p1.get()))
1223 {
1224 throw uno::RuntimeException(
1225 "librdf_Repository::exportGraph: "
1226 "librdf_serializer_set_feature relativeURIs failed", *this);
1227 }
1228 // but do not write the base URI to the file!
1229 if (librdf_serializer_set_feature(pSerializer.get(),
1230 pWriteBaseURI.get(), p0.get()))
1231 {
1232 throw uno::RuntimeException(
1233 "librdf_Repository::exportGraph: "
1234 "librdf_serializer_set_feature writeBaseURI failed", *this);
1235 }
1236
1237 size_t length;
1238 const std::shared_ptr<unsigned char> pBuf(
1239 librdf_serializer_serialize_stream_to_counted_string(
1240 pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free);
1241 if (!pBuf) {
1242 throw rdf::RepositoryException(
1243 "librdf_Repository::exportGraph: "
1244 "librdf_serializer_serialize_stream_to_counted_string failed",
1245 *this);
1246 }
1247
1248 g.unlock(); // release Mutex before calling i_xOutStream methods
1249
1250 addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
1251}
1252
1253uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
1254librdf_Repository::getGraphNames()
1255{
1256 std::scoped_lock g(m_aMutex);
1257 ::std::vector< uno::Reference<rdf::XURI> > ret;
1258 std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(),
1259 std::back_inserter(ret),
1260 [](std::pair<OUString, ::rtl::Reference<librdf_NamedGraph>> const& it)
1261 { return it.second->getName(); });
1263}
1264
1265uno::Reference< rdf::XNamedGraph > SAL_CALL
1266librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1267{
1268 if (!i_xGraphName.is()) {
1269 throw lang::IllegalArgumentException(
1270 "librdf_Repository::getGraph: URI is null", *this, 0);
1271 }
1272 const OUString contextU( i_xGraphName->getStringValue() );
1273
1274 std::scoped_lock g(m_aMutex);
1275 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
1276 if (iter != m_NamedGraphs.end()) {
1277 return iter->second;
1278 } else {
1279 return nullptr;
1280 }
1281}
1282
1283uno::Reference< rdf::XNamedGraph > SAL_CALL
1284librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1285{
1286 if (!i_xGraphName.is()) {
1287 throw lang::IllegalArgumentException(
1288 "librdf_Repository::createGraph: URI is null", *this, 0);
1289 }
1290
1291 const OUString contextU( i_xGraphName->getStringValue() );
1292 if (contextU.startsWith(s_nsOOo))
1293 {
1294 throw lang::IllegalArgumentException(
1295 "librdf_Repository::createGraph: URI is reserved", *this, 0);
1296 }
1297
1298 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1299
1300 // NB: librdf does not have a concept of graphs as such;
1301 // a librdf named graph exists iff the model contains a statement with
1302 // the graph name as context
1303
1304 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1305 throw container::ElementExistException(
1306 "librdf_Repository::createGraph: graph with given URI exists", *this);
1307 }
1308 m_NamedGraphs.insert(std::make_pair(contextU,
1309 new librdf_NamedGraph(this, i_xGraphName)));
1310 return m_NamedGraphs.find(contextU)->second;
1311}
1312
1313void SAL_CALL
1314librdf_Repository::destroyGraph(
1315 const uno::Reference< rdf::XURI > & i_xGraphName)
1316{
1317 if (!i_xGraphName.is()) {
1318 throw lang::IllegalArgumentException(
1319 "librdf_Repository::destroyGraph: URI is null", *this, 0);
1320 }
1321 const OUString contextU( i_xGraphName->getStringValue() );
1322
1323 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1324
1325 const NamedGraphMap_t::iterator iter( clearGraph_Lock(contextU, false) );
1326 m_NamedGraphs.erase(iter);
1327}
1328
1329bool isMetadatableWithoutMetadata(
1330 uno::Reference<uno::XInterface> const & i_xNode)
1331{
1332 const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY );
1333 return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty());
1334}
1335
1336uno::Reference< container::XEnumeration > SAL_CALL
1337librdf_Repository::getStatements(
1338 const uno::Reference< rdf::XResource > & i_xSubject,
1339 const uno::Reference< rdf::XURI > & i_xPredicate,
1340 const uno::Reference< rdf::XNode > & i_xObject)
1341{
1342 if (isMetadatableWithoutMetadata(i_xSubject) ||
1343 isMetadatableWithoutMetadata(i_xPredicate) ||
1344 isMetadatableWithoutMetadata(i_xObject))
1345 {
1346 return new librdf_GraphResult(this, m_aMutex,
1347 std::shared_ptr<librdf_stream>(),
1348 std::shared_ptr<librdf_node>());
1349 }
1350
1351 librdf_TypeConverter::Statement const stmt(
1352 librdf_TypeConverter::extractStatement_NoLock(
1353 i_xSubject, i_xPredicate, i_xObject));
1354
1355 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1356
1357 const std::shared_ptr<librdf_statement> pStatement(
1358 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1359 safe_librdf_free_statement);
1360 OSL_ENSURE(pStatement, "mkStatement failed");
1361
1362 const std::shared_ptr<librdf_stream> pStream(
1363 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1364 safe_librdf_free_stream);
1365 if (!pStream) {
1366 throw rdf::RepositoryException(
1367 "librdf_Repository::getStatements: "
1368 "librdf_model_find_statements failed", *this);
1369 }
1370
1371 return new librdf_GraphResult(this, m_aMutex, pStream,
1372 std::shared_ptr<librdf_node>());
1373}
1374
1375
1376uno::Reference< rdf::XQuerySelectResult > SAL_CALL
1377librdf_Repository::querySelect(const OUString & i_rQuery)
1378{
1379 std::scoped_lock g(m_aMutex);
1380 const OString query(
1381 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1382 const std::shared_ptr<librdf_query> pQuery(
1383 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1384 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1385 safe_librdf_free_query);
1386 if (!pQuery) {
1387 throw rdf::QueryException(
1388 "librdf_Repository::querySelect: "
1389 "librdf_new_query failed", *this);
1390 }
1391 const std::shared_ptr<librdf_query_results> pResults(
1392 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1393 safe_librdf_free_query_results);
1394 if (!pResults || !librdf_query_results_is_bindings(pResults.get())) {
1395 throw rdf::QueryException(
1396 "librdf_Repository::querySelect: "
1397 "query result is null or not bindings", *this);
1398 }
1399
1400 const int count( librdf_query_results_get_bindings_count(pResults.get()) );
1401 if (count < 0) {
1402 throw rdf::QueryException(
1403 "librdf_Repository::querySelect: "
1404 "librdf_query_results_get_bindings_count failed", *this);
1405 }
1406 uno::Sequence< OUString > names(count);
1407 auto namesRange = asNonConstRange(names);
1408 for (int i = 0; i < count; ++i) {
1409 const char* name( librdf_query_results_get_binding_name(
1410 pResults.get(), i) );
1411 if (!name) {
1412 throw rdf::QueryException(
1413 "librdf_Repository::querySelect: binding is null", *this);
1414 }
1415
1416 namesRange[i] = OUString::createFromAscii(name);
1417 }
1418
1419 return new librdf_QuerySelectResult(this, m_aMutex,
1420 pQuery, pResults, names);
1421}
1422
1423uno::Reference< container::XEnumeration > SAL_CALL
1424librdf_Repository::queryConstruct(const OUString & i_rQuery)
1425{
1426 std::scoped_lock g(m_aMutex);
1427 const OString query(
1428 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1429 const std::shared_ptr<librdf_query> pQuery(
1430 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1431 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1432 safe_librdf_free_query);
1433 if (!pQuery) {
1434 throw rdf::QueryException(
1435 "librdf_Repository::queryConstruct: "
1436 "librdf_new_query failed", *this);
1437 }
1438 const std::shared_ptr<librdf_query_results> pResults(
1439 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1440 safe_librdf_free_query_results);
1441 if (!pResults || !librdf_query_results_is_graph(pResults.get())) {
1442 throw rdf::QueryException(
1443 "librdf_Repository::queryConstruct: "
1444 "query result is null or not graph", *this);
1445 }
1446 const std::shared_ptr<librdf_stream> pStream(
1447 librdf_query_results_as_stream(pResults.get()),
1448 safe_librdf_free_stream);
1449 if (!pStream) {
1450 throw rdf::QueryException(
1451 "librdf_Repository::queryConstruct: "
1452 "librdf_query_results_as_stream failed", *this);
1453 }
1454
1455 return new librdf_GraphResult(this, m_aMutex, pStream,
1456 std::shared_ptr<librdf_node>(), pQuery);
1457}
1458
1459sal_Bool SAL_CALL
1460librdf_Repository::queryAsk(const OUString & i_rQuery)
1461{
1462 std::scoped_lock g(m_aMutex);
1463
1464 const OString query(
1465 OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1466 const std::shared_ptr<librdf_query> pQuery(
1467 librdf_new_query(m_pWorld.get(), s_sparql, nullptr,
1468 reinterpret_cast<const unsigned char*> (query.getStr()), nullptr),
1469 safe_librdf_free_query);
1470 if (!pQuery) {
1471 throw rdf::QueryException(
1472 "librdf_Repository::queryAsk: "
1473 "librdf_new_query failed", *this);
1474 }
1475 const std::shared_ptr<librdf_query_results> pResults(
1476 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1477 safe_librdf_free_query_results);
1478 if (!pResults || !librdf_query_results_is_boolean(pResults.get())) {
1479 throw rdf::QueryException(
1480 "librdf_Repository::queryAsk: "
1481 "query result is null or not boolean", *this);
1482 }
1483 return bool(librdf_query_results_get_boolean(pResults.get()));
1484}
1485
1486// css::rdf::XDocumentRepository:
1487void SAL_CALL librdf_Repository::setStatementRDFa(
1488 const uno::Reference< rdf::XResource > & i_xSubject,
1489 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
1490 const uno::Reference< rdf::XMetadatable > & i_xObject,
1491 const OUString & i_rRDFaContent,
1492 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
1493{
1494 if (!i_xSubject.is()) {
1495 throw lang::IllegalArgumentException(
1496 "librdf_Repository::setStatementRDFa: Subject is null", *this, 0);
1497 }
1498 if (!i_rPredicates.hasElements()) {
1499 throw lang::IllegalArgumentException(
1500 "librdf_Repository::setStatementRDFa: no Predicates",
1501 *this, 1);
1502 }
1503 if (std::any_of(i_rPredicates.begin(), i_rPredicates.end(),
1504 [](const uno::Reference< rdf::XURI >& rPredicate) { return !rPredicate.is(); })) {
1505 throw lang::IllegalArgumentException(
1506 "librdf_Repository::setStatementRDFa: Predicate is null", *this, 1);
1507 }
1508 if (!i_xObject.is()) {
1509 throw lang::IllegalArgumentException(
1510 "librdf_Repository::setStatementRDFa: Object is null", *this, 2);
1511 }
1512 const uno::Reference<lang::XServiceInfo> xService(i_xObject,
1513 uno::UNO_QUERY_THROW);
1514 uno::Reference<text::XTextRange> xTextRange;
1515 if (xService->supportsService("com.sun.star.table.Cell") ||
1516 xService->supportsService("com.sun.star.text.CellProperties") || // for writer
1517 xService->supportsService("com.sun.star.text.Paragraph"))
1518 {
1519 xTextRange.set(i_xObject, uno::UNO_QUERY_THROW);
1520 }
1521 else if (xService->supportsService("com.sun.star.text.Bookmark") ||
1522 xService->supportsService("com.sun.star.text.InContentMetadata"))
1523 {
1524 const uno::Reference<text::XTextContent> xTextContent(i_xObject,
1525 uno::UNO_QUERY_THROW);
1526 xTextRange = xTextContent->getAnchor();
1527 }
1528 if (!xTextRange.is()) {
1529 throw lang::IllegalArgumentException(
1530 "librdf_Repository::setStatementRDFa: "
1531 "Object does not support RDFa", *this, 2);
1532 }
1533 // ensure that the metadatable has an XML ID
1534 i_xObject->ensureMetadataReference();
1535 const beans::StringPair mdref( i_xObject->getMetadataReference() );
1536 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1537 throw uno::RuntimeException(
1538 "librdf_Repository::setStatementRDFa: "
1539 "ensureMetadataReference did not", *this);
1540 }
1541 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1542 OUString const sContext(s_nsOOo + sXmlId);
1543 OUString const content( (i_rRDFaContent.isEmpty())
1544 ? xTextRange->getString()
1545 : i_rRDFaContent );
1546 uno::Reference<rdf::XNode> xContent;
1547 try {
1548 if (i_xRDFaDatatype.is()) {
1549 xContent.set(rdf::Literal::createWithType(m_xContext,
1550 content, i_xRDFaDatatype),
1551 uno::UNO_QUERY_THROW);
1552 } else {
1553 xContent.set(rdf::Literal::create(m_xContext, content),
1554 uno::UNO_QUERY_THROW);
1555 }
1556 } catch (const lang::IllegalArgumentException &) {
1557 css::uno::Any anyEx = cppu::getCaughtException();
1558 throw lang::WrappedTargetRuntimeException(
1559 "librdf_Repository::setStatementRDFa: "
1560 "cannot create literal", *this, anyEx);
1561 }
1562
1563 std::shared_ptr<librdf_TypeConverter::Resource> const pSubject(
1564 librdf_TypeConverter::extractResource_NoLock(i_xSubject));
1565 std::shared_ptr<librdf_TypeConverter::Node> const pContent(
1566 librdf_TypeConverter::extractNode_NoLock(xContent));
1567 ::std::vector< std::shared_ptr<librdf_TypeConverter::Resource> >
1568 predicates;
1569 ::std::transform(i_rPredicates.begin(), i_rPredicates.end(),
1570 ::std::back_inserter(predicates),
1571 [](uno::Reference<rdf::XURI> const& xURI)
1572 { return librdf_TypeConverter::extractResource_NoLock(xURI); });
1573
1574 removeStatementRDFa(i_xObject); // not atomic with insertion?
1575
1576 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1577
1578 if (i_rRDFaContent.isEmpty()) {
1579 m_RDFaXHTMLContentSet.erase(sXmlId);
1580 } else {
1581 m_RDFaXHTMLContentSet.insert(sXmlId);
1582 }
1583 try
1584 {
1585 for (const auto& rPredicatePtr : predicates)
1586 {
1587 addStatementGraph_Lock(
1588 librdf_TypeConverter::Statement(pSubject,
1589 std::dynamic_pointer_cast<librdf_TypeConverter::URI>(rPredicatePtr),
1590 pContent),
1591 sContext, true);
1592 }
1593 }
1594 catch (const container::NoSuchElementException&)
1595 {
1596 css::uno::Any anyEx = cppu::getCaughtException();
1597 throw lang::WrappedTargetRuntimeException(
1598 "librdf_Repository::setStatementRDFa: "
1599 "cannot addStatementGraph", *this, anyEx);
1600 }
1601}
1602
1603void SAL_CALL librdf_Repository::removeStatementRDFa(
1604 const uno::Reference< rdf::XMetadatable > & i_xElement)
1605{
1606 if (!i_xElement.is()) {
1607 throw lang::IllegalArgumentException(
1608 "librdf_Repository::removeStatementRDFa: Element is null",
1609 *this, 0);
1610 }
1611
1612 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1613 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1614 return; // nothing to do...
1615 }
1616
1617 OUString const sXmlId(s_nsOOo + mdref.First + "#" + mdref.Second);
1618
1619 clearGraph_NoLock(sXmlId, true);
1620}
1621
1622beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
1623librdf_Repository::getStatementRDFa(
1624 const uno::Reference< rdf::XMetadatable > & i_xElement)
1625{
1626 if (!i_xElement.is()) {
1627 throw lang::IllegalArgumentException(
1628 "librdf_Repository::getStatementRDFa: Element is null", *this, 0);
1629 }
1630 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1631 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1632 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >();
1633 }
1634 OUString const sXmlId(mdref.First + "#" + mdref.Second);
1635 uno::Reference<rdf::XURI> xXmlId;
1636 try {
1637 xXmlId.set( rdf::URI::create(m_xContext, s_nsOOo + sXmlId),
1638 uno::UNO_SET_THROW);
1639 } catch (const lang::IllegalArgumentException &) {
1640 css::uno::Any anyEx = cppu::getCaughtException();
1641 throw lang::WrappedTargetRuntimeException(
1642 "librdf_Repository::getStatementRDFa: "
1643 "cannot create URI for XML ID", *this, anyEx);
1644 }
1645
1646 ::std::vector< rdf::Statement > ret;
1647 try
1648 {
1649 ret = getStatementsGraph_NoLock(nullptr, nullptr, nullptr, xXmlId, true);
1650 }
1651 catch (const container::NoSuchElementException&)
1652 {
1653 css::uno::Any anyEx = cppu::getCaughtException();
1654 throw lang::WrappedTargetRuntimeException(
1655 "librdf_Repository::getStatementRDFa: "
1656 "cannot getStatementsGraph", *this, anyEx);
1657 }
1658
1659 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1660
1661 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
1662 comphelper::containerToSequence(ret), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
1663}
1664
1665extern "C"
1666librdf_statement *rdfa_context_stream_map_handler(
1667 librdf_stream *i_pStream, void *, librdf_statement *i_pStatement)
1668{
1669 OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null");
1670 if (i_pStream) {
1671 librdf_node *pCtxt(
1672#if LIBRDF_VERSION >= 10012
1673 librdf_stream_get_context2(i_pStream) );
1674#else
1675 static_cast<librdf_node *>(librdf_stream_get_context(i_pStream)) );
1676#endif
1677 OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null");
1678 if (pCtxt && isInternalContext(pCtxt)) {
1679 return i_pStatement;
1680 }
1681 }
1682 return nullptr;
1683};
1684
1685uno::Reference< container::XEnumeration > SAL_CALL
1686librdf_Repository::getStatementsRDFa(
1687 const uno::Reference< rdf::XResource > & i_xSubject,
1688 const uno::Reference< rdf::XURI > & i_xPredicate,
1689 const uno::Reference< rdf::XNode > & i_xObject)
1690{
1691 if (isMetadatableWithoutMetadata(i_xSubject) ||
1692 isMetadatableWithoutMetadata(i_xPredicate) ||
1693 isMetadatableWithoutMetadata(i_xObject))
1694 {
1695 return new librdf_GraphResult(this, m_aMutex,
1696 std::shared_ptr<librdf_stream>(),
1697 std::shared_ptr<librdf_node>());
1698 }
1699
1700 librdf_TypeConverter::Statement const stmt(
1701 librdf_TypeConverter::extractStatement_NoLock(
1702 i_xSubject, i_xPredicate, i_xObject));
1703
1704 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1705
1706 const std::shared_ptr<librdf_statement> pStatement(
1707 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1708 safe_librdf_free_statement);
1709 OSL_ENSURE(pStatement, "mkStatement failed");
1710
1711 const std::shared_ptr<librdf_stream> pStream(
1712 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1713 safe_librdf_free_stream);
1714 if (!pStream) {
1715 throw rdf::RepositoryException(
1716 "librdf_Repository::getStatementsRDFa: "
1717 "librdf_model_find_statements failed", *this);
1718 }
1719
1720 if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler,
1721 nullptr, nullptr)) {
1722 throw rdf::RepositoryException(
1723 "librdf_Repository::getStatementsRDFa: "
1724 "librdf_stream_add_map failed", *this);
1725 }
1726
1727 return new librdf_GraphResult(this, m_aMutex, pStream,
1728 std::shared_ptr<librdf_node>());
1729}
1730
1731// css::lang::XInitialization:
1732void SAL_CALL librdf_Repository::initialize(
1733 const uno::Sequence< css::uno::Any > &)
1734{
1735 std::scoped_lock g(m_aMutex);
1736
1737// m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
1738 m_pStorage.reset(m_TypeConverter.createStorage_Lock(m_pWorld.get()),
1739 safe_librdf_free_storage);
1740 m_pModel.reset(m_TypeConverter.createModel_Lock(
1741 m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
1742}
1743
1744NamedGraphMap_t::iterator librdf_Repository::clearGraph_NoLock(
1745 OUString const& i_rGraphName, bool i_Internal)
1746// throw (uno::RuntimeException, container::NoSuchElementException,
1747// rdf::RepositoryException)
1748{
1749 std::scoped_lock g(m_aMutex);
1750
1751 return clearGraph_Lock(i_rGraphName, i_Internal);
1752}
1753
1754NamedGraphMap_t::iterator librdf_Repository::clearGraph_Lock(
1755 OUString const& i_rGraphName, bool i_Internal)
1756{
1757 // internal: must be called with mutex locked!
1758 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(i_rGraphName) );
1759 if (!i_Internal && iter == m_NamedGraphs.end()) {
1760 throw container::NoSuchElementException(
1761 "librdf_Repository::clearGraph: "
1762 "no graph with given URI exists", *this);
1763 }
1764 const OString context(
1765 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1766
1767 const std::shared_ptr<librdf_node> pContext(
1768 librdf_new_node_from_uri_string(m_pWorld.get(),
1769 reinterpret_cast<const unsigned char*> (context.getStr())),
1770 safe_librdf_free_node);
1771 if (!pContext) {
1772 throw uno::RuntimeException(
1773 "librdf_Repository::clearGraph: "
1774 "librdf_new_node_from_uri_string failed", *this);
1775 }
1776 if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get()))
1777 {
1778 throw rdf::RepositoryException(
1779 "librdf_Repository::clearGraph: "
1780 "librdf_model_context_remove_statements failed", *this);
1781 }
1782 return iter;
1783}
1784
1785void librdf_Repository::addStatementGraph_NoLock(
1786 const uno::Reference< rdf::XResource > & i_xSubject,
1787 const uno::Reference< rdf::XURI > & i_xPredicate,
1788 const uno::Reference< rdf::XNode > & i_xObject,
1789 const uno::Reference< rdf::XURI > & i_xGraphName)
1790//throw (uno::RuntimeException, lang::IllegalArgumentException,
1791// container::NoSuchElementException, rdf::RepositoryException)
1792{
1793 if (!i_xSubject.is()) {
1794 throw lang::IllegalArgumentException(
1795 "librdf_Repository::addStatement: Subject is null", *this, 0);
1796 }
1797 if (!i_xPredicate.is()) {
1798 throw lang::IllegalArgumentException(
1799 "librdf_Repository::addStatement: Predicate is null",
1800 *this, 1);
1801 }
1802 if (!i_xObject.is()) {
1803 throw lang::IllegalArgumentException(
1804 "librdf_Repository::addStatement: Object is null", *this, 2);
1805 }
1806
1807 librdf_TypeConverter::Statement const stmt(
1808 librdf_TypeConverter::extractStatement_NoLock(
1809 i_xSubject, i_xPredicate, i_xObject));
1810
1811 const OUString contextU( i_xGraphName->getStringValue() );
1812
1813 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1814
1815 addStatementGraph_Lock(stmt, contextU, false/*i_Internal*/);
1816}
1817
1818void librdf_Repository::addStatementGraph_Lock(
1819 librdf_TypeConverter::Statement const& i_rStatement,
1820 OUString const& i_rGraphName,
1821 bool i_Internal)
1822{
1823 if (!i_Internal
1824 && (m_NamedGraphs.find(i_rGraphName) == m_NamedGraphs.end()))
1825 {
1826 throw container::NoSuchElementException(
1827 "librdf_Repository::addStatement: "
1828 "no graph with given URI exists", *this);
1829 }
1830 const OString context(
1831 OUStringToOString(i_rGraphName, RTL_TEXTENCODING_UTF8) );
1832
1833 const std::shared_ptr<librdf_node> pContext(
1834 librdf_new_node_from_uri_string(m_pWorld.get(),
1835 reinterpret_cast<const unsigned char*> (context.getStr())),
1836 safe_librdf_free_node);
1837 if (!pContext) {
1838 throw uno::RuntimeException(
1839 "librdf_Repository::addStatement: "
1840 "librdf_new_node_from_uri_string failed", *this);
1841 }
1842 const std::shared_ptr<librdf_statement> pStatement(
1843 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), i_rStatement),
1844 safe_librdf_free_statement);
1845 OSL_ENSURE(pStatement, "mkStatement failed");
1846
1847 // Test for duplicate statement
1848 // librdf_model_add_statement disallows duplicates while
1849 // librdf_model_context_add_statement allows duplicates
1850 {
1851 const std::shared_ptr<librdf_stream> pStream(
1852 librdf_model_find_statements_in_context(m_pModel.get(),
1853 pStatement.get(), pContext.get()),
1854 safe_librdf_free_stream);
1855 if (pStream && !librdf_stream_end(pStream.get()))
1856 return;
1857 }
1858
1859 if (librdf_model_context_add_statement(m_pModel.get(),
1860 pContext.get(), pStatement.get())) {
1861 throw rdf::RepositoryException(
1862 "librdf_Repository::addStatement: "
1863 "librdf_model_context_add_statement failed", *this);
1864 }
1865}
1866
1867void librdf_Repository::removeStatementsGraph_NoLock(
1868 const uno::Reference< rdf::XResource > & i_xSubject,
1869 const uno::Reference< rdf::XURI > & i_xPredicate,
1870 const uno::Reference< rdf::XNode > & i_xObject,
1871 const uno::Reference< rdf::XURI > & i_xGraphName)
1872//throw (uno::RuntimeException, lang::IllegalArgumentException,
1873// container::NoSuchElementException, rdf::RepositoryException)
1874{
1875 if (isMetadatableWithoutMetadata(i_xSubject) ||
1876 isMetadatableWithoutMetadata(i_xPredicate) ||
1877 isMetadatableWithoutMetadata(i_xObject))
1878 {
1879 return;
1880 }
1881
1882 librdf_TypeConverter::Statement const stmt(
1883 librdf_TypeConverter::extractStatement_NoLock(
1884 i_xSubject, i_xPredicate, i_xObject));
1885 const OUString contextU( i_xGraphName->getStringValue() );
1886
1887 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1888
1889 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1890 throw container::NoSuchElementException(
1891 "librdf_Repository::removeStatements: "
1892 "no graph with given URI exists", *this);
1893 }
1894 const OString context(
1895 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1896
1897 const std::shared_ptr<librdf_node> pContext(
1898 librdf_new_node_from_uri_string(m_pWorld.get(),
1899 reinterpret_cast<const unsigned char*> (context.getStr())),
1900 safe_librdf_free_node);
1901 if (!pContext) {
1902 throw uno::RuntimeException(
1903 "librdf_Repository::removeStatements: "
1904 "librdf_new_node_from_uri_string failed", *this);
1905 }
1906 const std::shared_ptr<librdf_statement> pStatement(
1907 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1908 safe_librdf_free_statement);
1909 OSL_ENSURE(pStatement, "mkStatement failed");
1910
1911 const std::shared_ptr<librdf_stream> pStream(
1912 librdf_model_find_statements_in_context(m_pModel.get(),
1913 pStatement.get(), pContext.get()),
1914 safe_librdf_free_stream);
1915 if (!pStream) {
1916 throw rdf::RepositoryException(
1917 "librdf_Repository::removeStatements: "
1918 "librdf_model_find_statements_in_context failed", *this);
1919 }
1920
1921 if (librdf_stream_end(pStream.get()))
1922 return;
1923
1924 do {
1925 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
1926 if (!pStmt) {
1927 throw rdf::RepositoryException(
1928 "librdf_Repository::removeStatements: "
1929 "librdf_stream_get_object failed", *this);
1930 }
1931 if (librdf_model_context_remove_statement(m_pModel.get(),
1932 pContext.get(), pStmt)) {
1933 throw rdf::RepositoryException(
1934 "librdf_Repository::removeStatements: "
1935 "librdf_model_context_remove_statement failed", *this);
1936 }
1937 } while (!librdf_stream_next(pStream.get()));
1938}
1939
1940std::vector<rdf::Statement>
1941librdf_Repository::getStatementsGraph_NoLock(
1942 const uno::Reference< rdf::XResource > & i_xSubject,
1943 const uno::Reference< rdf::XURI > & i_xPredicate,
1944 const uno::Reference< rdf::XNode > & i_xObject,
1945 const uno::Reference< rdf::XURI > & i_xGraphName,
1946 bool i_Internal)
1947//throw (uno::RuntimeException, lang::IllegalArgumentException,
1948// container::NoSuchElementException, rdf::RepositoryException)
1949{
1950 std::vector<rdf::Statement> ret;
1951
1952 // N.B.: if any of subject, predicate, object is an XMetadatable, and
1953 // has no metadata reference, then there cannot be any node in the graph
1954 // representing it; in order to prevent side effect
1955 // (ensureMetadataReference), check for this condition and return
1956 if (isMetadatableWithoutMetadata(i_xSubject) ||
1957 isMetadatableWithoutMetadata(i_xPredicate) ||
1958 isMetadatableWithoutMetadata(i_xObject))
1959 {
1960 return ret;
1961 }
1962
1963 librdf_TypeConverter::Statement const stmt(
1964 librdf_TypeConverter::extractStatement_NoLock(
1965 i_xSubject, i_xPredicate, i_xObject));
1966 const OUString contextU( i_xGraphName->getStringValue() );
1967
1968 std::scoped_lock g(m_aMutex); // don't call i_x* with mutex locked
1969
1970 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1971 throw container::NoSuchElementException(
1972 "librdf_Repository::getStatements: "
1973 "no graph with given URI exists", *this);
1974 }
1975 const OString context(
1976 OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1977
1978 const std::shared_ptr<librdf_node> pContext(
1979 librdf_new_node_from_uri_string(m_pWorld.get(),
1980 reinterpret_cast<const unsigned char*> (context.getStr())),
1981 safe_librdf_free_node);
1982 if (!pContext) {
1983 throw uno::RuntimeException(
1984 "librdf_Repository::getStatements: "
1985 "librdf_new_node_from_uri_string failed", *this);
1986 }
1987 const std::shared_ptr<librdf_statement> pStatement(
1988 librdf_TypeConverter::mkStatement_Lock(m_pWorld.get(), stmt),
1989 safe_librdf_free_statement);
1990 OSL_ENSURE(pStatement, "mkStatement failed");
1991
1992 const std::shared_ptr<librdf_stream> pStream(
1993 librdf_model_find_statements_in_context(m_pModel.get(),
1994 pStatement.get(), pContext.get()),
1995 safe_librdf_free_stream);
1996 if (!pStream) {
1997 throw rdf::RepositoryException(
1998 "librdf_Repository::getStatements: "
1999 "librdf_model_find_statements_in_context failed", *this);
2000 }
2001
2002 librdf_node *pCtxt1(
2003#if LIBRDF_VERSION >= 10012
2004 librdf_stream_get_context2(pStream.get()) );
2005#else
2006 static_cast<librdf_node *>(librdf_stream_get_context(pStream.get())) );
2007#endif
2008 while (!librdf_stream_end(pStream.get()))
2009 {
2010 auto pCtxt = pCtxt1;
2011 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
2012 if (!pStmt) {
2013 rdf::QueryException e(
2014 "librdf_GraphResult::nextElement: "
2015 "librdf_stream_get_object failed", *this);
2016 throw lang::WrappedTargetException(
2017 "librdf_GraphResult::nextElement: "
2018 "librdf_stream_get_object failed", *this,
2019 uno::Any(e));
2020 }
2021 // NB: pCtxt may be null here if this is result of a graph query
2022 if (pCtxt && isInternalContext(pCtxt)) {
2023 pCtxt = nullptr; // XML ID context is implementation detail!
2024 }
2025
2026 ret.emplace_back(
2027 getTypeConverter().convertToStatement(pStmt, pCtxt) );
2028
2029 // NB: this will invalidate current item.
2030 librdf_stream_next(pStream.get());
2031 }
2032
2033 return ret;
2034}
2035
2036extern "C"
2037void librdf_raptor_init(void* /*user_data*/, raptor_world* pRaptorWorld)
2038{
2039 // fdo#64672 prevent raptor from setting global libxml2 error handlers
2040 raptor_world_set_flag(pRaptorWorld,
2041 RAPTOR_WORLD_FLAG_LIBXML_STRUCTURED_ERROR_SAVE, 0);
2042 raptor_world_set_flag(pRaptorWorld,
2043 RAPTOR_WORLD_FLAG_LIBXML_GENERIC_ERROR_SAVE, 0);
2044}
2045
2046librdf_world *librdf_TypeConverter::createWorld_Lock() const
2047{
2048 // create and initialize world
2049 librdf_world *pWorld( librdf_new_world() );
2050 if (!pWorld) {
2051 throw uno::RuntimeException(
2052 "librdf_TypeConverter::createWorld: librdf_new_world failed",
2053 m_rRep);
2054 }
2055 librdf_world_set_raptor_init_handler(pWorld, nullptr, &librdf_raptor_init);
2056 //FIXME logger, digest, features?
2057 xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs();
2058 librdf_world_open(pWorld);
2059 xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs();
2060 if (newprefs != origprefs) {
2061 // #i110523# restore libxslt global configuration
2062 // (gratuitously overwritten by raptor_init_parser_grddl_common)
2063 // (this is the only reason unordf is linked against libxslt)
2064 xsltSetDefaultSecurityPrefs(origprefs);
2065 }
2066 return pWorld;
2067}
2068
2069librdf_storage *
2070librdf_TypeConverter::createStorage_Lock(librdf_world *i_pWorld) const
2071{
2072 librdf_storage *pStorage(
2073// librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
2074 librdf_new_storage(i_pWorld, "hashes", nullptr,
2075 "contexts='yes',hash-type='memory'") );
2076 if (!pStorage) {
2077 throw uno::RuntimeException(
2078 "librdf_TypeConverter::createStorage: librdf_new_storage failed",
2079 m_rRep);
2080 }
2081 return pStorage;
2082}
2083
2084librdf_model *librdf_TypeConverter::createModel_Lock(
2085 librdf_world *i_pWorld, librdf_storage * i_pStorage) const
2086{
2087 librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, nullptr) );
2088 if (!pRepository) {
2089 throw uno::RuntimeException(
2090 "librdf_TypeConverter::createModel: librdf_new_model failed",
2091 m_rRep);
2092 }
2093 //FIXME
2094#if 0
2095 {
2096 librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS));
2097 librdf_node * contexts = librdf_model_get_feature(repository, ctxt);
2098 if (!contexts)
2099 throw;
2100 std::cout << "value of contexts feature: ";
2101 prtNode(contexts);
2102 std::cout << std::endl;
2103 // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...);
2104 safe_librdf_free_node(contexts);
2105 safe_librdf_free_uri(ctxt);
2106 }
2107#endif
2108 return pRepository;
2109}
2110
2111// this does NOT create a node, only URI
2112librdf_uri* librdf_TypeConverter::mkURI_Lock( librdf_world* i_pWorld,
2113 OString const& i_rURI)
2114{
2115 librdf_uri *pURI( librdf_new_uri(i_pWorld,
2116 reinterpret_cast<const unsigned char *>(i_rURI.getStr())));
2117 if (!pURI) {
2118 throw uno::RuntimeException(
2119 "librdf_TypeConverter::mkURI: librdf_new_uri failed", nullptr);
2120 }
2121 return pURI;
2122}
2123
2124// extract blank or URI node - call without Mutex locked
2125std::shared_ptr<librdf_TypeConverter::Resource>
2126librdf_TypeConverter::extractResource_NoLock(
2127 const uno::Reference< rdf::XResource > & i_xResource)
2128{
2129 if (!i_xResource.is()) {
2130 return std::shared_ptr<Resource>();
2131 }
2132 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2133 if (xBlankNode.is()) {
2134 const OString label(
2135 OUStringToOString(xBlankNode->getStringValue(),
2136 RTL_TEXTENCODING_UTF8) );
2137 return std::make_shared<BlankNode>(label);
2138 } else { // assumption: everything else is URI
2139 const OString uri(
2140 OUStringToOString(i_xResource->getStringValue(),
2141 RTL_TEXTENCODING_UTF8) );
2142 return std::make_shared<URI>(uri);
2143 }
2144}
2145
2146void
2147librdf_TypeConverter::extractResourceToCacheKey_NoLock(
2148 const uno::Reference< rdf::XResource > & i_xResource, OUStringBuffer& rBuffer)
2149{
2150 if (!i_xResource.is()) {
2151 return;
2152 }
2153 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
2154 if (xBlankNode.is()) {
2155 rBuffer.append("BlankNode " + xBlankNode->getStringValue());
2156 } else { // assumption: everything else is URI
2157 rBuffer.append("URI " + i_xResource->getStringValue());
2158 }
2159}
2160
2161// create blank or URI node
2162librdf_node* librdf_TypeConverter::mkResource_Lock( librdf_world* i_pWorld,
2163 Resource const*const i_pResource)
2164{
2165 if (!i_pResource) return nullptr;
2166 BlankNode const*const pBlankNode(
2167 dynamic_cast<BlankNode const*>(i_pResource));
2168 if (pBlankNode) {
2169 librdf_node *pNode(
2170 librdf_new_node_from_blank_identifier(i_pWorld,
2171 reinterpret_cast<const unsigned char*>(
2172 pBlankNode->value.getStr())));
2173 if (!pNode) {
2174 throw uno::RuntimeException(
2175 "librdf_TypeConverter::mkResource: "
2176 "librdf_new_node_from_blank_identifier failed", nullptr);
2177 }
2178 return pNode;
2179 } else { // assumption: everything else is URI
2180 URI const*const pURI(dynamic_cast<URI const*>(i_pResource));
2181 assert(pURI);
2182 librdf_node *pNode(
2183 librdf_new_node_from_uri_string(i_pWorld,
2184 reinterpret_cast<const unsigned char*>(pURI->value.getStr())));
2185 if (!pNode) {
2186 throw uno::RuntimeException(
2187 "librdf_TypeConverter::mkResource: "
2188 "librdf_new_node_from_uri_string failed", nullptr);
2189 }
2190 return pNode;
2191 }
2192}
2193
2194// extract blank or URI or literal node - call without Mutex locked
2195std::shared_ptr<librdf_TypeConverter::Node>
2196librdf_TypeConverter::extractNode_NoLock(
2197 const uno::Reference< rdf::XNode > & i_xNode)
2198{
2199 if (!i_xNode.is()) {
2200 return std::shared_ptr<Node>();
2201 }
2202 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2203 if (xResource.is()) {
2204 return extractResource_NoLock(xResource);
2205 }
2206 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2207 OSL_ENSURE(xLiteral.is(),
2208 "mkNode: someone invented a new rdf.XNode and did not tell me");
2209 if (!xLiteral.is()) {
2210 return std::shared_ptr<Node>();
2211 }
2212 const OString val(
2213 OUStringToOString(xLiteral->getValue(),
2214 RTL_TEXTENCODING_UTF8) );
2215 const OString lang(
2216 OUStringToOString(xLiteral->getLanguage(),
2217 RTL_TEXTENCODING_UTF8) );
2218 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2219 std::optional<OString> type;
2220 if (xType.is())
2221 {
2222 type =
2223 OUStringToOString(xType->getStringValue(), RTL_TEXTENCODING_UTF8);
2224 }
2225 return std::make_shared<Literal>(val, lang, type);
2226}
2227
2228// extract blank or URI or literal node - call without Mutex locked
2229void
2230librdf_TypeConverter::extractNodeToCacheKey_NoLock(
2231 const uno::Reference< rdf::XNode > & i_xNode,
2232 OUStringBuffer& rBuffer)
2233{
2234 if (!i_xNode.is()) {
2235 return;
2236 }
2237 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2238 if (xResource.is()) {
2239 return extractResourceToCacheKey_NoLock(xResource, rBuffer);
2240 }
2241 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2242 OSL_ENSURE(xLiteral.is(),
2243 "mkNode: someone invented a new rdf.XNode and did not tell me");
2244 if (!xLiteral.is()) {
2245 return;
2246 }
2247 rBuffer.append("Literal " + xLiteral->getValue() + "\t" + xLiteral->getLanguage());
2248 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2249 if (xType.is())
2250 rBuffer.append("\t" + xType->getStringValue());
2251}
2252
2253// create blank or URI or literal node
2254librdf_node* librdf_TypeConverter::mkNode_Lock( librdf_world* i_pWorld,
2255 Node const*const i_pNode)
2256{
2257 if (!i_pNode) return nullptr;
2258 Resource const*const pResource(dynamic_cast<Resource const*>(i_pNode));
2259 if (pResource) {
2260 return mkResource_Lock(i_pWorld, pResource);
2261 }
2262
2263 Literal const*const pLiteral(dynamic_cast<Literal const*>(i_pNode));
2264 assert(pLiteral);
2265 librdf_node * ret(nullptr);
2266 if (pLiteral->language.isEmpty()) {
2267 if (!pLiteral->type) {
2268 ret = librdf_new_node_from_literal(i_pWorld,
2269 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2270 , nullptr, 0);
2271 } else {
2272 const std::shared_ptr<librdf_uri> pDatatype(
2273 mkURI_Lock(i_pWorld, *pLiteral->type),
2274 safe_librdf_free_uri);
2275 ret = librdf_new_node_from_typed_literal(i_pWorld,
2276 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2277 , nullptr, pDatatype.get());
2278 }
2279 } else {
2280 if (!pLiteral->type) {
2281 ret = librdf_new_node_from_literal(i_pWorld,
2282 reinterpret_cast<const unsigned char*>(pLiteral->value.getStr())
2283 , pLiteral->language.getStr(), 0);
2284 } else {
2285 OSL_FAIL("mkNode: invalid literal");
2286 return nullptr;
2287 }
2288 }
2289 if (!ret) {
2290 throw uno::RuntimeException(
2291 "librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed", nullptr);
2292 }
2293 return ret;
2294}
2295
2296// extract statement - call without Mutex locked
2297librdf_TypeConverter::Statement librdf_TypeConverter::extractStatement_NoLock(
2298 const uno::Reference< rdf::XResource > & i_xSubject,
2299 const uno::Reference< rdf::XURI > & i_xPredicate,
2300 const uno::Reference< rdf::XNode > & i_xObject)
2301{
2302 std::shared_ptr<Resource> const pSubject(
2303 extractResource_NoLock(i_xSubject));
2304 std::shared_ptr<URI> const pPredicate(
2305 std::dynamic_pointer_cast<URI>(extractResource_NoLock(i_xPredicate)));
2306 std::shared_ptr<Node> const pObject(extractNode_NoLock(i_xObject));
2307 return Statement(pSubject, pPredicate, pObject);
2308}
2309
2310librdf_statement* librdf_TypeConverter::mkStatement_Lock(librdf_world* i_pWorld,
2311 Statement const& i_rStatement)
2312{
2313 librdf_node *const pSubject(
2314 mkResource_Lock(i_pWorld, i_rStatement.pSubject.get()) );
2315 librdf_node* pPredicate(nullptr);
2316 librdf_node* pObject(nullptr);
2317 try {
2318 pPredicate = mkResource_Lock(i_pWorld, i_rStatement.pPredicate.get());
2319 try {
2320 pObject = mkNode_Lock(i_pWorld, i_rStatement.pObject.get());
2321 } catch (...) {
2322 safe_librdf_free_node(pPredicate);
2323 throw;
2324 }
2325 } catch (...) {
2326 safe_librdf_free_node(pSubject);
2327 throw;
2328 }
2329 // NB: this takes ownership of the nodes! (which is really ugly)
2330 librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld,
2331 pSubject, pPredicate, pObject) );
2332 if (!pStatement) {
2333 throw uno::RuntimeException(
2334 "librdf_TypeConverter::mkStatement: "
2335 "librdf_new_statement_from_nodes failed", nullptr);
2336 }
2337 return pStatement;
2338}
2339
2340uno::Reference<rdf::XURI>
2341librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const
2342{
2343 if (!i_pURI) return nullptr;
2344 const unsigned char* uri( librdf_uri_as_string(i_pURI) );
2345 if (!uri) {
2346 throw uno::RuntimeException(
2347 "librdf_TypeConverter::convertToXURI: "
2348 "librdf_uri_as_string failed", m_rRep);
2349 }
2350 OUString uriU( OStringToOUString(
2351 std::string_view(reinterpret_cast<const char*>(uri)),
2352 RTL_TEXTENCODING_UTF8) );
2353 try {
2354 return rdf::URI::create(m_xContext, uriU);
2355 } catch (const lang::IllegalArgumentException &) {
2356 css::uno::Any anyEx = cppu::getCaughtException();
2357 throw lang::WrappedTargetRuntimeException(
2358 "librdf_TypeConverter::convertToXURI: "
2359 "illegal uri", m_rRep, anyEx);
2360 }
2361}
2362
2363uno::Reference<rdf::XURI>
2364librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const
2365{
2366 if (!i_pNode) return nullptr;
2367 if (librdf_node_is_resource(i_pNode)) {
2368 librdf_uri* pURI( librdf_node_get_uri(i_pNode) );
2369 if (!pURI) {
2370 throw uno::RuntimeException(
2371 "librdf_TypeConverter::convertToXURI: "
2372 "resource has no uri", m_rRep);
2373 }
2374 return convertToXURI(pURI);
2375 } else {
2376 OSL_FAIL("convertToXURI: unknown librdf_node");
2377 return nullptr;
2378 }
2379}
2380
2381uno::Reference<rdf::XResource>
2382librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const
2383{
2384 if (!i_pNode) return nullptr;
2385 if (librdf_node_is_blank(i_pNode)) {
2386 const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) );
2387 if (!label) {
2388 throw uno::RuntimeException(
2389 "librdf_TypeConverter::convertToXResource: "
2390 "blank node has no label", m_rRep);
2391 }
2392 OUString labelU( OStringToOUString(
2393 std::string_view(reinterpret_cast<const char*>(label)),
2394 RTL_TEXTENCODING_UTF8) );
2395 try {
2396 return rdf::BlankNode::create(m_xContext, labelU);
2397 } catch (const lang::IllegalArgumentException &) {
2398 css::uno::Any anyEx = cppu::getCaughtException();
2399 throw lang::WrappedTargetRuntimeException(
2400 "librdf_TypeConverter::convertToXResource: "
2401 "illegal blank node label", m_rRep, anyEx);
2402 }
2403 } else {
2404 return convertToXURI(i_pNode);
2405 }
2406}
2407
2408uno::Reference<rdf::XNode>
2409librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const
2410{
2411 if (!i_pNode) return nullptr;
2412 if (!librdf_node_is_literal(i_pNode)) {
2413 return convertToXResource(i_pNode);
2414 }
2415 const unsigned char* value( librdf_node_get_literal_value(i_pNode) );
2416 if (!value) {
2417 throw uno::RuntimeException(
2418 "librdf_TypeConverter::convertToXNode: "
2419 "literal has no value", m_rRep);
2420 }
2421 const char * lang( librdf_node_get_literal_value_language(i_pNode) );
2422 librdf_uri* pType(
2423 librdf_node_get_literal_value_datatype_uri(i_pNode) );
2424 OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal");
2425 const OUString valueU( OStringToOUString(
2426 std::string_view(reinterpret_cast<const char*>(value)),
2427 RTL_TEXTENCODING_UTF8) );
2428 if (lang) {
2429 const OUString langU( OStringToOUString(
2430 std::string_view(lang),
2431 RTL_TEXTENCODING_UTF8) );
2432 return rdf::Literal::createWithLanguage(m_xContext, valueU, langU);
2433 } else if (pType) {
2434 uno::Reference<rdf::XURI> xType(convertToXURI(pType));
2435 OSL_ENSURE(xType.is(), "convertToXNode: null uri");
2436 return rdf::Literal::createWithType(m_xContext, valueU, xType);
2437 } else {
2438 return rdf::Literal::create(m_xContext, valueU);
2439 }
2440}
2441
2442rdf::Statement
2443librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt,
2444 librdf_node* i_pContext) const
2445{
2446 if (!i_pStmt) {
2447 throw uno::RuntimeException();
2448 }
2449 return rdf::Statement(
2450 convertToXResource(librdf_statement_get_subject(i_pStmt)),
2451 convertToXURI(librdf_statement_get_predicate(i_pStmt)),
2452 convertToXNode(librdf_statement_get_object(i_pStmt)),
2453 convertToXURI(i_pContext));
2454}
2455
2456} // closing anonymous implementation namespace
2457
2458
2459extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2461 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
2462{
2463 return cppu::acquire(new librdf_Repository(context));
2464}
2465
2466/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
Any value
::osl::Mutex & m_rMutex
Reference< XOutputStream > stream
Definition: document.cxx:332
EmbeddedObjectRef * pObject
GtkMediaStream * m_pStream
std::mutex m_aMutex
const char * name
sal_Int64 n
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * unoxml_rdfRepository_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
def label(st)
OString makeXMLChaff()
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
int i
enumrange< T >::Iterator begin(enumrange< T >)
VBAHELPER_DLLPUBLIC css::uno::Reference< css::script::XTypeConverter > const & getTypeConverter(const css::uno::Reference< css::uno::XComponentContext > &xContext)
end
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
store_handle_type *SAL_CALL query(OStoreObject *pHandle, store_handle_type *)
unsigned char sal_Bool
signed char sal_Int8
ResultType type