Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / unoxml / source / rdf / librdf_repository.cxx
blob830eef916884aef4fe4974a968c883a0e7c2fafa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "librdf_repository.hxx"
31 #include <string.h>
33 #include <set>
34 #include <map>
35 #include <functional>
36 #include <algorithm>
38 #include <boost/utility.hpp>
39 #include <boost/shared_ptr.hpp>
40 #include <boost/shared_array.hpp>
41 #include <boost/bind.hpp>
43 #include <libxslt/security.h>
45 #include <redland.h>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/lang/XInitialization.hpp>
49 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
50 #include <com/sun/star/lang/IllegalArgumentException.hpp>
51 #include <com/sun/star/io/XSeekableInputStream.hpp>
52 #include <com/sun/star/text/XTextRange.hpp>
53 #include <com/sun/star/rdf/XDocumentRepository.hpp>
54 #include <com/sun/star/rdf/XLiteral.hpp>
55 #include <com/sun/star/rdf/FileFormat.hpp>
56 #include <com/sun/star/rdf/URIs.hpp>
57 #include <com/sun/star/rdf/BlankNode.hpp>
58 #include <com/sun/star/rdf/URI.hpp>
59 #include <com/sun/star/rdf/Literal.hpp>
61 #include <rtl/ref.hxx>
62 #include <rtl/ustring.hxx>
63 #include <cppuhelper/implbase1.hxx>
64 #include <cppuhelper/implbase3.hxx>
65 #include <cppuhelper/basemutex.hxx>
67 #include <comphelper/stlunosequence.hxx>
68 #include <comphelper/sequenceasvector.hxx>
69 #include <comphelper/makesequence.hxx>
70 #include <comphelper/xmltools.hxx>
72 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
74 /**
75 Implementation of the service com.sun.star.rdf.Repository.
77 This implementation uses the Redland RDF library (librdf).
79 There are several classes involved:
80 librdf_TypeConverter: helper class to convert data types redland <-> uno
81 librdf_Repository: the main repository, does almost all the work
82 librdf_NamedGraph: the XNamedGraph, forwards everything to repository
83 librdf_GraphResult: an XEnumeration<Statement>
84 librdf_QuerySelectResult: an XEnumeration<sequence<XNode>>
86 @author mst
89 /// anonymous implementation namespace
90 namespace {
92 class librdf_NamedGraph;
93 class librdf_Repository;
95 using namespace ::com::sun::star;
97 typedef std::map< ::rtl::OUString, ::rtl::Reference<librdf_NamedGraph> >
98 NamedGraphMap_t;
100 const char s_sparql [] = "sparql";
101 const char s_nsRDFs [] = "http://www.w3.org/2000/01/rdf-schema#";
102 const char s_label [] = "label";
103 const char s_nsOOo [] = "http://openoffice.org/2004/office/rdfa/";
105 ////////////////////////////////////////////////////////////////////////////
107 //FIXME: this approach is not ideal. can we use blind nodes instead?
108 bool isInternalContext(librdf_node *i_pNode) throw ()
110 OSL_ENSURE(i_pNode, "isInternalContext: context null");
111 OSL_ENSURE(librdf_node_is_resource(i_pNode),
112 "isInternalContext: context not resource");
113 if (i_pNode) {
114 librdf_uri *pURI(librdf_node_get_uri(i_pNode));
115 OSL_ENSURE(pURI, "isInternalContext: URI null");
116 if (pURI) {
117 unsigned char *pContextURI(librdf_uri_as_string(pURI));
118 OSL_ENSURE(pContextURI,
119 "isInternalContext: URI string null");
120 // if prefix matches reserved uri, it is RDFa context
121 if (!strncmp(reinterpret_cast<char *>(pContextURI),
122 s_nsOOo, sizeof(s_nsOOo)-1)) {
123 return true;
126 return false;
128 return true;
132 ////////////////////////////////////////////////////////////////////////////
134 // n.b.: librdf destructor functions dereference null pointers!
135 // so they need to be wrapped to be usable with boost::shared_ptr.
136 static void safe_librdf_free_world(librdf_world *const world)
138 if (world) { librdf_free_world(world); }
140 static void safe_librdf_free_model(librdf_model *const model)
142 if (model) { librdf_free_model(model); }
144 static void safe_librdf_free_node(librdf_node* node)
146 if (node) { librdf_free_node(node); }
148 static void safe_librdf_free_parser(librdf_parser *const parser)
150 if (parser) { librdf_free_parser(parser); }
152 static void safe_librdf_free_query(librdf_query *const query)
154 if (query) { librdf_free_query(query); }
156 static void
157 safe_librdf_free_query_results(librdf_query_results *const query_results)
159 if (query_results) { librdf_free_query_results(query_results); }
161 static void safe_librdf_free_serializer(librdf_serializer *const serializer)
163 if (serializer) { librdf_free_serializer(serializer); }
165 static void safe_librdf_free_statement(librdf_statement *const statement)
167 if (statement) { librdf_free_statement(statement); }
169 static void safe_librdf_free_storage(librdf_storage *const storage)
171 if (storage) { librdf_free_storage(storage); }
173 static void safe_librdf_free_stream(librdf_stream *const stream)
175 if (stream) { librdf_free_stream(stream); }
177 static void safe_librdf_free_uri(librdf_uri *const uri)
179 if (uri) { librdf_free_uri(uri); }
183 ////////////////////////////////////////////////////////////////////////////
185 /** converts between librdf types and UNO API types.
187 class librdf_TypeConverter
189 public:
190 librdf_TypeConverter(
191 uno::Reference< uno::XComponentContext > const & i_xContext,
192 librdf_Repository &i_rRep)
193 : m_xContext(i_xContext)
194 , m_rRep(i_rRep)
195 { };
197 librdf_world *createWorld() const;
198 librdf_storage *createStorage(librdf_world *i_pWorld) const;
199 librdf_model *createModel(librdf_world *i_pWorld,
200 librdf_storage * i_pStorage) const;
201 librdf_uri* mkURI( librdf_world* i_pWorld,
202 const uno::Reference< rdf::XURI > & i_xURI) const;
203 librdf_node* mkResource( librdf_world* i_pWorld,
204 const uno::Reference< rdf::XResource > & i_xResource) const;
205 librdf_node* mkNode( librdf_world* i_pWorld,
206 const uno::Reference< rdf::XNode > & i_xNode) const;
207 librdf_statement* mkStatement( librdf_world* i_pWorld,
208 const uno::Reference< rdf::XResource > & i_xSubject,
209 const uno::Reference< rdf::XURI > & i_xPredicate,
210 const uno::Reference< rdf::XNode > & i_xObject) const;
211 uno::Reference<rdf::XURI> convertToXURI(librdf_uri* i_pURI) const;
212 uno::Reference<rdf::XURI> convertToXURI(librdf_node* i_pURI) const;
213 uno::Reference<rdf::XResource>
214 convertToXResource(librdf_node* i_pNode) const;
215 uno::Reference<rdf::XNode> convertToXNode(librdf_node* i_pNode) const;
216 rdf::Statement
217 convertToStatement(librdf_statement* i_pStmt, librdf_node* i_pContext)
218 const;
220 private:
221 uno::Reference< uno::XComponentContext > m_xContext;
222 librdf_Repository & m_rRep;
226 ////////////////////////////////////////////////////////////////////////////
228 /** implements the repository service.
230 class librdf_Repository:
231 private boost::noncopyable,
232 // private ::cppu::BaseMutex,
233 public ::cppu::WeakImplHelper3<
234 lang::XServiceInfo,
235 rdf::XDocumentRepository,
236 lang::XInitialization>
238 public:
240 explicit librdf_Repository(
241 uno::Reference< uno::XComponentContext > const & i_xContext);
242 virtual ~librdf_Repository();
244 // ::com::sun::star::lang::XServiceInfo:
245 virtual ::rtl::OUString SAL_CALL getImplementationName()
246 throw (uno::RuntimeException);
247 virtual ::sal_Bool SAL_CALL supportsService(
248 const ::rtl::OUString & ServiceName) throw (uno::RuntimeException);
249 virtual uno::Sequence< ::rtl::OUString > SAL_CALL
250 getSupportedServiceNames() throw (uno::RuntimeException);
252 // ::com::sun::star::rdf::XRepository:
253 virtual uno::Reference< rdf::XBlankNode > SAL_CALL createBlankNode()
254 throw (uno::RuntimeException);
255 virtual uno::Reference<rdf::XNamedGraph> SAL_CALL importGraph(
256 ::sal_Int16 i_Format,
257 const uno::Reference< io::XInputStream > & i_xInStream,
258 const uno::Reference< rdf::XURI > & i_xGraphName,
259 const uno::Reference< rdf::XURI > & i_xBaseURI)
260 throw (uno::RuntimeException, lang::IllegalArgumentException,
261 datatransfer::UnsupportedFlavorException,
262 container::ElementExistException, rdf::ParseException,
263 rdf::RepositoryException, io::IOException);
264 virtual void SAL_CALL exportGraph(::sal_Int16 i_Format,
265 const uno::Reference< io::XOutputStream > & i_xOutStream,
266 const uno::Reference< rdf::XURI > & i_xGraphName,
267 const uno::Reference< rdf::XURI > & i_xBaseURI)
268 throw (uno::RuntimeException, lang::IllegalArgumentException,
269 datatransfer::UnsupportedFlavorException,
270 container::NoSuchElementException, rdf::RepositoryException,
271 io::IOException);
272 virtual uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
273 getGraphNames() throw (uno::RuntimeException, rdf::RepositoryException);
274 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL getGraph(
275 const uno::Reference< rdf::XURI > & i_xGraphName)
276 throw (uno::RuntimeException, lang::IllegalArgumentException,
277 rdf::RepositoryException);
278 virtual uno::Reference< rdf::XNamedGraph > SAL_CALL createGraph(
279 const uno::Reference< rdf::XURI > & i_xGraphName)
280 throw (uno::RuntimeException, lang::IllegalArgumentException,
281 container::ElementExistException, rdf::RepositoryException);
282 virtual void SAL_CALL destroyGraph(
283 const uno::Reference< rdf::XURI > & i_xGraphName)
284 throw (uno::RuntimeException, lang::IllegalArgumentException,
285 container::NoSuchElementException, rdf::RepositoryException);
286 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
287 const uno::Reference< rdf::XResource > & i_xSubject,
288 const uno::Reference< rdf::XURI > & i_xPredicate,
289 const uno::Reference< rdf::XNode > & i_xObject)
290 throw (uno::RuntimeException,
291 rdf::RepositoryException);
292 virtual uno::Reference< rdf::XQuerySelectResult > SAL_CALL
293 querySelect(const ::rtl::OUString & i_rQuery)
294 throw (uno::RuntimeException, rdf::QueryException,
295 rdf::RepositoryException);
296 virtual uno::Reference< container::XEnumeration > SAL_CALL
297 queryConstruct(const ::rtl::OUString & i_rQuery)
298 throw (uno::RuntimeException, rdf::QueryException,
299 rdf::RepositoryException);
300 virtual ::sal_Bool SAL_CALL queryAsk(const ::rtl::OUString & i_rQuery)
301 throw (uno::RuntimeException, rdf::QueryException,
302 rdf::RepositoryException);
304 // ::com::sun::star::rdf::XDocumentRepository:
305 virtual void SAL_CALL setStatementRDFa(
306 const uno::Reference< rdf::XResource > & i_xSubject,
307 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
308 const uno::Reference< rdf::XMetadatable > & i_xObject,
309 const ::rtl::OUString & i_rRDFaContent,
310 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
311 throw (uno::RuntimeException, lang::IllegalArgumentException,
312 rdf::RepositoryException);
313 virtual void SAL_CALL removeStatementRDFa(
314 const uno::Reference< rdf::XMetadatable > & i_xElement)
315 throw (uno::RuntimeException, lang::IllegalArgumentException,
316 rdf::RepositoryException);
317 virtual beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
318 getStatementRDFa(uno::Reference< rdf::XMetadatable > const& i_xElement)
319 throw (uno::RuntimeException, lang::IllegalArgumentException,
320 rdf::RepositoryException);
321 virtual uno::Reference< container::XEnumeration > SAL_CALL
322 getStatementsRDFa(
323 const uno::Reference< rdf::XResource > & i_xSubject,
324 const uno::Reference< rdf::XURI > & i_xPredicate,
325 const uno::Reference< rdf::XNode > & i_xObject)
326 throw (uno::RuntimeException,
327 rdf::RepositoryException);
329 // ::com::sun::star::lang::XInitialization:
330 virtual void SAL_CALL initialize(
331 const uno::Sequence< ::com::sun::star::uno::Any > & i_rArguments)
332 throw (uno::RuntimeException, uno::Exception);
334 // XNamedGraph forwards ---------------------------------------------
335 const NamedGraphMap_t::iterator SAL_CALL clearGraph(
336 const uno::Reference< rdf::XURI > & i_xName,
337 bool i_Internal = false );
338 void addStatementGraph(
339 const uno::Reference< rdf::XResource > & i_xSubject,
340 const uno::Reference< rdf::XURI > & i_xPredicate,
341 const uno::Reference< rdf::XNode > & i_xObject,
342 const uno::Reference< rdf::XURI > & i_xName,
343 bool i_Internal = false );
344 // throw (uno::RuntimeException, lang::IllegalArgumentException,
345 // container::NoSuchElementException, rdf::RepositoryException);
346 void removeStatementsGraph(
347 const uno::Reference< rdf::XResource > & i_xSubject,
348 const uno::Reference< rdf::XURI > & i_xPredicate,
349 const uno::Reference< rdf::XNode > & i_xObject,
350 const uno::Reference< rdf::XURI > & i_xName );
351 // throw (uno::RuntimeException, lang::IllegalArgumentException,
352 // container::NoSuchElementException, rdf::RepositoryException);
353 uno::Reference< container::XEnumeration > getStatementsGraph(
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 bool i_Internal = false );
359 // throw (uno::RuntimeException, lang::IllegalArgumentException,
360 // container::NoSuchElementException, rdf::RepositoryException);
362 const librdf_TypeConverter& getTypeConverter() { return m_TypeConverter; };
364 private:
366 uno::Reference< uno::XComponentContext > m_xContext;
368 /// librdf global data
369 /** N.B.: The redland documentation gives the impression that you can have
370 as many librdf_worlds as you like. This is true in the same sense
371 that you can physically be in as many places as you like.
372 Well, you can, just not at the same time.
373 The ugly truth is that destroying a librdf_world kills a bunch
374 of static variables; other librdf_worlds become very unhappy
375 when they access these.
376 And of course this is not documented anywhere that I could find.
377 So we allocate a single world, and refcount that.
379 static boost::shared_ptr<librdf_world> m_pWorld;
380 /// refcount
381 static sal_uInt32 m_NumInstances;
382 /// mutex for m_pWorld - redland is not as threadsafe as is often claimed
383 static osl::Mutex m_aMutex;
385 // NB: sequence of the shared pointers is important!
386 /// librdf repository storage
387 boost::shared_ptr<librdf_storage> m_pStorage;
388 /// librdf repository model
389 boost::shared_ptr<librdf_model> m_pModel;
391 /// all named graphs
392 NamedGraphMap_t m_NamedGraphs;
394 /// type conversion helper
395 librdf_TypeConverter m_TypeConverter;
397 /// set of xml:ids of elements with xhtml:content
398 ::std::set< ::rtl::OUString > m_RDFaXHTMLContentSet;
402 ////////////////////////////////////////////////////////////////////////////
404 /** result of operations that return a graph, i.e.,
405 an XEnumeration of statements.
407 class librdf_GraphResult:
408 private boost::noncopyable,
409 public ::cppu::WeakImplHelper1<
410 container::XEnumeration>
412 public:
414 librdf_GraphResult(librdf_Repository *i_pRepository,
415 ::osl::Mutex & i_rMutex,
416 boost::shared_ptr<librdf_stream> const& i_pStream,
417 boost::shared_ptr<librdf_node> const& i_pContext,
418 boost::shared_ptr<librdf_query> const& i_pQuery =
419 boost::shared_ptr<librdf_query>() )
420 : m_xRep(i_pRepository)
421 , m_rMutex(i_rMutex)
422 , m_pQuery(i_pQuery)
423 , m_pContext(i_pContext)
424 , m_pStream(i_pStream)
425 { };
427 virtual ~librdf_GraphResult() {}
429 // ::com::sun::star::container::XEnumeration:
430 virtual ::sal_Bool SAL_CALL hasMoreElements()
431 throw (uno::RuntimeException);
432 virtual uno::Any SAL_CALL nextElement()
433 throw (uno::RuntimeException, container::NoSuchElementException,
434 lang::WrappedTargetException);
436 private:
437 // NB: this is not a weak pointer: streams _must_ be deleted before the
438 // storage they point into, so we keep the repository alive here
439 // also, sequence is important: the stream must be destroyed first.
440 ::rtl::Reference< librdf_Repository > m_xRep;
441 // needed for synchronizing access to librdf (it doesnt do win32 threading)
442 ::osl::Mutex & m_rMutex;
443 // the query (in case this is a result of a graph query)
444 // not that the redland documentation spells this out explicity, but
445 // queries must be freed only after all the results are completely read
446 boost::shared_ptr<librdf_query> const m_pQuery;
447 boost::shared_ptr<librdf_node> const m_pContext;
448 boost::shared_ptr<librdf_stream> const m_pStream;
450 librdf_node* getContext() const;
454 // ::com::sun::star::container::XEnumeration:
455 ::sal_Bool SAL_CALL
456 librdf_GraphResult::hasMoreElements() throw (uno::RuntimeException)
458 ::osl::MutexGuard g(m_rMutex);
459 return m_pStream.get() && !librdf_stream_end(m_pStream.get());
462 librdf_node* librdf_GraphResult::getContext() const
464 if (!m_pStream.get() || librdf_stream_end(m_pStream.get()))
465 return NULL;
466 SAL_WNODEPRECATED_DECLARATIONS_PUSH;
467 librdf_node *pCtxt( static_cast<librdf_node *>
468 (librdf_stream_get_context(m_pStream.get())) );
469 SAL_WNODEPRECATED_DECLARATIONS_POP;
470 if (pCtxt)
471 return pCtxt;
472 return m_pContext.get();
475 ::com::sun::star::uno::Any SAL_CALL
476 librdf_GraphResult::nextElement()
477 throw (uno::RuntimeException, container::NoSuchElementException,
478 lang::WrappedTargetException)
480 ::osl::MutexGuard g(m_rMutex);
481 if (!m_pStream.get() || !librdf_stream_end(m_pStream.get())) {
482 librdf_node * pCtxt = getContext();
484 librdf_statement *pStmt( librdf_stream_get_object(m_pStream.get()) );
485 if (!pStmt) {
486 rdf::QueryException e(
487 "librdf_GraphResult::nextElement: "
488 "librdf_stream_get_object failed", *this);
489 throw lang::WrappedTargetException(
490 "librdf_GraphResult::nextElement: "
491 "librdf_stream_get_object failed", *this,
492 uno::makeAny(e));
494 // NB: pCtxt may be null here if this is result of a graph query
495 if (pCtxt && isInternalContext(pCtxt)) {
496 pCtxt = 0; // XML ID context is implementation detail!
498 rdf::Statement Stmt(
499 m_xRep->getTypeConverter().convertToStatement(pStmt, pCtxt) );
500 // NB: this will invalidate current item.
501 librdf_stream_next(m_pStream.get());
502 return uno::makeAny(Stmt);
503 } else {
504 throw container::NoSuchElementException();
509 ////////////////////////////////////////////////////////////////////////////
511 /** result of tuple queries ("SELECT").
513 class librdf_QuerySelectResult:
514 private boost::noncopyable,
515 public ::cppu::WeakImplHelper1<
516 rdf::XQuerySelectResult>
518 public:
520 librdf_QuerySelectResult(librdf_Repository *i_pRepository,
521 ::osl::Mutex & i_rMutex,
522 boost::shared_ptr<librdf_query> const& i_pQuery,
523 boost::shared_ptr<librdf_query_results> const& i_pQueryResult,
524 uno::Sequence< ::rtl::OUString > const& i_rBindingNames )
525 : m_xRep(i_pRepository)
526 , m_rMutex(i_rMutex)
527 , m_pQuery(i_pQuery)
528 , m_pQueryResult(i_pQueryResult)
529 , m_BindingNames(i_rBindingNames)
530 { };
532 virtual ~librdf_QuerySelectResult() {}
534 // ::com::sun::star::container::XEnumeration:
535 virtual ::sal_Bool SAL_CALL hasMoreElements()
536 throw (uno::RuntimeException);
537 virtual uno::Any SAL_CALL nextElement()
538 throw (uno::RuntimeException, container::NoSuchElementException,
539 lang::WrappedTargetException);
541 // ::com::sun::star::rdf::XQuerySelectResult:
542 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getBindingNames()
543 throw (uno::RuntimeException);
545 private:
547 // NB: this is not a weak pointer: streams _must_ be deleted before the
548 // storage they point into, so we keep the repository alive here
549 // also, sequence is important: the stream must be destroyed first.
550 ::rtl::Reference< librdf_Repository > m_xRep;
551 // needed for synchronizing access to librdf (it doesnt do win32 threading)
552 ::osl::Mutex & m_rMutex;
553 // not that the redland documentation spells this out explicity, but
554 // queries must be freed only after all the results are completely read
555 boost::shared_ptr<librdf_query> m_pQuery;
556 boost::shared_ptr<librdf_query_results> m_pQueryResult;
557 uno::Sequence< ::rtl::OUString > m_BindingNames;
561 // ::com::sun::star::container::XEnumeration:
562 ::sal_Bool SAL_CALL
563 librdf_QuerySelectResult::hasMoreElements() throw (uno::RuntimeException)
565 ::osl::MutexGuard g(m_rMutex);
566 return !librdf_query_results_finished(m_pQueryResult.get());
569 class NodeArrayDeleter : public std::unary_function<librdf_node**, void>
571 const int m_Count;
573 public:
574 NodeArrayDeleter(int i_Count) : m_Count(i_Count) { }
576 void operator() (librdf_node** io_pArray) const throw ()
578 std::for_each(io_pArray, io_pArray + m_Count, safe_librdf_free_node);
579 delete[] io_pArray;
583 ::com::sun::star::uno::Any SAL_CALL
584 librdf_QuerySelectResult::nextElement()
585 throw (uno::RuntimeException, container::NoSuchElementException,
586 lang::WrappedTargetException)
588 ::osl::MutexGuard g(m_rMutex);
589 if (!librdf_query_results_finished(m_pQueryResult.get())) {
590 sal_Int32 count(m_BindingNames.getLength());
591 OSL_ENSURE(count >= 0, "negative length?");
592 boost::shared_array<librdf_node*> pNodes( new librdf_node*[count],
593 NodeArrayDeleter(count));
594 for (int i = 0; i < count; ++i) {
595 pNodes[i] = 0;
597 if (librdf_query_results_get_bindings(m_pQueryResult.get(), NULL,
598 pNodes.get()))
600 rdf::QueryException e(
601 "librdf_QuerySelectResult::nextElement: "
602 "librdf_query_results_get_bindings failed", *this);
603 throw lang::WrappedTargetException(
604 "librdf_QuerySelectResult::nextElement: "
605 "librdf_query_results_get_bindings failed", *this,
606 uno::makeAny(e));
608 uno::Sequence< uno::Reference< rdf::XNode > > ret(count);
609 for (int i = 0; i < count; ++i) {
610 ret[i] = m_xRep->getTypeConverter().convertToXNode(pNodes[i]);
612 // NB: this will invalidate current item.
613 librdf_query_results_next(m_pQueryResult.get());
614 return uno::makeAny(ret);
615 } else {
616 throw container::NoSuchElementException();
620 // ::com::sun::star::rdf::XQuerySelectResult:
621 uno::Sequence< ::rtl::OUString > SAL_CALL
622 librdf_QuerySelectResult::getBindingNames() throw (uno::RuntimeException)
624 return m_BindingNames;
628 ////////////////////////////////////////////////////////////////////////////
630 /** represents a named graph, and forwards all the work to repository.
632 class librdf_NamedGraph:
633 private boost::noncopyable,
634 public ::cppu::WeakImplHelper1<
635 rdf::XNamedGraph>
637 public:
638 librdf_NamedGraph(librdf_Repository * i_pRep,
639 uno::Reference<rdf::XURI> const & i_xName)
640 : m_wRep(i_pRep)
641 , m_pRep(i_pRep)
642 , m_xName(i_xName)
643 { };
645 virtual ~librdf_NamedGraph() {}
647 // ::com::sun::star::rdf::XNode:
648 virtual ::rtl::OUString SAL_CALL getStringValue()
649 throw (uno::RuntimeException);
651 // ::com::sun::star::rdf::XURI:
652 virtual ::rtl::OUString SAL_CALL getNamespace()
653 throw (uno::RuntimeException);
654 virtual ::rtl::OUString SAL_CALL getLocalName()
655 throw (uno::RuntimeException);
657 // ::com::sun::star::rdf::XNamedGraph:
658 virtual uno::Reference<rdf::XURI> SAL_CALL getName()
659 throw (uno::RuntimeException);
660 virtual void SAL_CALL clear()
661 throw (uno::RuntimeException,
662 container::NoSuchElementException, rdf::RepositoryException);
663 virtual void SAL_CALL addStatement(
664 const uno::Reference< rdf::XResource > & i_xSubject,
665 const uno::Reference< rdf::XURI > & i_xPredicate,
666 const uno::Reference< rdf::XNode > & i_xObject)
667 throw (uno::RuntimeException, lang::IllegalArgumentException,
668 container::NoSuchElementException, rdf::RepositoryException);
669 virtual void SAL_CALL removeStatements(
670 const uno::Reference< rdf::XResource > & i_xSubject,
671 const uno::Reference< rdf::XURI > & i_xPredicate,
672 const uno::Reference< rdf::XNode > & i_xObject)
673 throw (uno::RuntimeException,
674 container::NoSuchElementException, rdf::RepositoryException);
675 virtual uno::Reference< container::XEnumeration > SAL_CALL getStatements(
676 const uno::Reference< rdf::XResource > & i_xSubject,
677 const uno::Reference< rdf::XURI > & i_xPredicate,
678 const uno::Reference< rdf::XNode > & i_xObject)
679 throw (uno::RuntimeException,
680 container::NoSuchElementException, rdf::RepositoryException);
682 private:
684 /// weak reference: this is needed to check if m_pRep is valid
685 uno::WeakReference< rdf::XRepository > m_wRep;
686 librdf_Repository *m_pRep;
687 uno::Reference< rdf::XURI > m_xName;
691 // ::com::sun::star::rdf::XNode:
692 ::rtl::OUString SAL_CALL librdf_NamedGraph::getStringValue()
693 throw (uno::RuntimeException)
695 return m_xName->getStringValue();
698 // ::com::sun::star::rdf::XURI:
699 ::rtl::OUString SAL_CALL librdf_NamedGraph::getNamespace()
700 throw (uno::RuntimeException)
702 return m_xName->getNamespace();
705 ::rtl::OUString SAL_CALL librdf_NamedGraph::getLocalName()
706 throw (uno::RuntimeException)
708 return m_xName->getLocalName();
711 // ::com::sun::star::rdf::XNamedGraph:
712 uno::Reference< rdf::XURI > SAL_CALL librdf_NamedGraph::getName()
713 throw (uno::RuntimeException)
715 return m_xName;
718 void SAL_CALL librdf_NamedGraph::clear()
719 throw (uno::RuntimeException,
720 container::NoSuchElementException, rdf::RepositoryException)
722 uno::Reference< rdf::XRepository > xRep( m_wRep );
723 if (!xRep.is()) {
724 throw rdf::RepositoryException(
725 "librdf_NamedGraph::clear: repository is gone", *this);
727 try {
728 m_pRep->clearGraph(m_xName);
729 } catch (lang::IllegalArgumentException &) {
730 throw uno::RuntimeException();
734 void SAL_CALL librdf_NamedGraph::addStatement(
735 const uno::Reference< rdf::XResource > & i_xSubject,
736 const uno::Reference< rdf::XURI > & i_xPredicate,
737 const uno::Reference< rdf::XNode > & i_xObject)
738 throw (uno::RuntimeException, lang::IllegalArgumentException,
739 container::NoSuchElementException, rdf::RepositoryException)
741 uno::Reference< rdf::XRepository > xRep( m_wRep );
742 if (!xRep.is()) {
743 throw rdf::RepositoryException(
744 "librdf_NamedGraph::addStatement: repository is gone", *this);
746 m_pRep->addStatementGraph(i_xSubject, i_xPredicate, i_xObject, m_xName);
749 void SAL_CALL librdf_NamedGraph::removeStatements(
750 const uno::Reference< rdf::XResource > & i_xSubject,
751 const uno::Reference< rdf::XURI > & i_xPredicate,
752 const uno::Reference< rdf::XNode > & i_xObject)
753 throw (uno::RuntimeException,
754 container::NoSuchElementException, rdf::RepositoryException)
756 uno::Reference< rdf::XRepository > xRep( m_wRep );
757 if (!xRep.is()) {
758 throw rdf::RepositoryException(
759 "librdf_NamedGraph::removeStatements: repository is gone", *this);
761 m_pRep->removeStatementsGraph(i_xSubject, i_xPredicate, i_xObject, m_xName);
764 uno::Reference< container::XEnumeration > SAL_CALL
765 librdf_NamedGraph::getStatements(
766 const uno::Reference< rdf::XResource > & i_xSubject,
767 const uno::Reference< rdf::XURI > & i_xPredicate,
768 const uno::Reference< rdf::XNode > & i_xObject)
769 throw (uno::RuntimeException,
770 container::NoSuchElementException, rdf::RepositoryException)
772 uno::Reference< rdf::XRepository > xRep( m_wRep );
773 if (!xRep.is()) {
774 throw rdf::RepositoryException(
775 "librdf_NamedGraph::getStatements: repository is gone", *this);
777 return m_pRep->getStatementsGraph(
778 i_xSubject, i_xPredicate, i_xObject, m_xName);
782 ////////////////////////////////////////////////////////////////////////////
784 boost::shared_ptr<librdf_world> librdf_Repository::m_pWorld;
785 sal_uInt32 librdf_Repository::m_NumInstances = 0;
786 osl::Mutex librdf_Repository::m_aMutex;
788 librdf_Repository::librdf_Repository(
789 uno::Reference< uno::XComponentContext > const & i_xContext)
790 : /*BaseMutex(),*/ m_xContext(i_xContext)
791 // m_pWorld (static_cast<librdf_world *>(0), safe_librdf_free_world ),
792 , m_pStorage(static_cast<librdf_storage*>(0), safe_librdf_free_storage)
793 , m_pModel (static_cast<librdf_model *>(0), safe_librdf_free_model )
794 , m_NamedGraphs()
795 , m_TypeConverter(i_xContext, *this)
797 OSL_ENSURE(i_xContext.is(), "librdf_Repository: null context");
799 ::osl::MutexGuard g(m_aMutex);
800 if (!m_NumInstances++) {
801 m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
805 librdf_Repository::~librdf_Repository()
807 // must destroy these before world!
808 m_pModel.reset();
809 m_pStorage.reset();
811 // FIXME: so it turns out that calling librdf_free_world will
812 // (via raptor_sax2_finish) call xmlCleanupParser, which will
813 // free libxml2's globals! ARRRGH!!! => never call librdf_free_world
814 #if 0
815 ::osl::MutexGuard g(m_aMutex);
816 if (!--m_NumInstances) {
817 m_pWorld.reset();
819 #endif
822 // com.sun.star.uno.XServiceInfo:
823 ::rtl::OUString SAL_CALL librdf_Repository::getImplementationName()
824 throw (uno::RuntimeException)
826 return comp_librdf_Repository::_getImplementationName();
829 ::sal_Bool SAL_CALL librdf_Repository::supportsService(
830 ::rtl::OUString const & serviceName) throw (uno::RuntimeException)
832 uno::Sequence< ::rtl::OUString > serviceNames
833 = comp_librdf_Repository::_getSupportedServiceNames();
834 for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
835 if (serviceNames[i] == serviceName)
836 return sal_True;
838 return sal_False;
841 uno::Sequence< ::rtl::OUString > SAL_CALL
842 librdf_Repository::getSupportedServiceNames() throw (uno::RuntimeException)
844 return comp_librdf_Repository::_getSupportedServiceNames();
847 // ::com::sun::star::rdf::XRepository:
848 uno::Reference< rdf::XBlankNode > SAL_CALL librdf_Repository::createBlankNode()
849 throw (uno::RuntimeException)
851 ::osl::MutexGuard g(m_aMutex);
852 const boost::shared_ptr<librdf_node> pNode(
853 librdf_new_node_from_blank_identifier(m_pWorld.get(), NULL),
854 safe_librdf_free_node);
855 if (!pNode) {
856 throw uno::RuntimeException(
857 "librdf_Repository::createBlankNode: "
858 "librdf_new_node_from_blank_identifier failed", *this);
860 const unsigned char * id (librdf_node_get_blank_identifier(pNode.get()));
861 if (!id) {
862 throw uno::RuntimeException(
863 "librdf_Repository::createBlankNode: "
864 "librdf_node_get_blank_identifier failed", *this);
866 const ::rtl::OUString nodeID(::rtl::OUString::createFromAscii(
867 reinterpret_cast<const char *>(id)));
868 try {
869 return rdf::BlankNode::create(m_xContext, nodeID);
870 } catch (const lang::IllegalArgumentException & iae) {
871 throw lang::WrappedTargetRuntimeException(
872 "librdf_Repository::createBlankNode: "
873 "illegal blank node label", *this, uno::makeAny(iae));
877 bool formatNeedsBaseURI(::sal_Int16 i_Format)
879 (void) i_Format; //FIXME any which dont?
880 return true;
883 //void SAL_CALL
884 uno::Reference<rdf::XNamedGraph> SAL_CALL
885 librdf_Repository::importGraph(::sal_Int16 i_Format,
886 const uno::Reference< io::XInputStream > & i_xInStream,
887 const uno::Reference< rdf::XURI > & i_xGraphName,
888 const uno::Reference< rdf::XURI > & i_xBaseURI)
889 throw (uno::RuntimeException, lang::IllegalArgumentException,
890 datatransfer::UnsupportedFlavorException,
891 container::ElementExistException, rdf::ParseException,
892 rdf::RepositoryException, io::IOException)
894 ::osl::MutexGuard g(m_aMutex);
895 if (!i_xInStream.is()) {
896 throw lang::IllegalArgumentException(
897 "librdf_Repository::importGraph: stream is null", *this, 1);
899 //FIXME: other formats
900 if (i_Format != rdf::FileFormat::RDF_XML) {
901 throw datatransfer::UnsupportedFlavorException(
902 "librdf_Repository::importGraph: file format not supported", *this);
904 if (!i_xGraphName.is()) {
905 throw lang::IllegalArgumentException(
906 "librdf_Repository::importGraph: graph name is null", *this, 2);
908 if (i_xGraphName->getStringValue().matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1))
910 throw lang::IllegalArgumentException(
911 "librdf_Repository::importGraph: URI is reserved", *this, 0);
913 if (formatNeedsBaseURI(i_Format) && !i_xBaseURI.is()) {
914 throw lang::IllegalArgumentException(
915 "librdf_Repository::importGraph: base URI is null", *this, 3);
917 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
918 const ::rtl::OUString baseURIU( i_xBaseURI->getStringValue() );
919 if (baseURIU.indexOf('#') >= 0) {
920 throw lang::IllegalArgumentException(
921 "librdf_Repository::importGraph: base URI is not absolute", *this, 3);
924 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
925 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
926 throw container::ElementExistException(
927 "librdf_Repository::importGraph: graph with given URI exists", *this);
929 const ::rtl::OString context(
930 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
932 const boost::shared_ptr<librdf_node> pContext(
933 librdf_new_node_from_uri_string(m_pWorld.get(),
934 reinterpret_cast<const unsigned char*> (context.getStr())),
935 safe_librdf_free_node);
936 if (!pContext) {
937 throw uno::RuntimeException(
938 "librdf_Repository::importGraph: librdf_new_node_from_uri_string failed", *this);
941 const ::rtl::OString baseURI(
942 ::rtl::OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
943 const boost::shared_ptr<librdf_uri> pBaseURI(
944 librdf_new_uri(m_pWorld.get(),
945 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
946 safe_librdf_free_uri);
947 if (!pBaseURI) {
948 throw uno::RuntimeException( "librdf_Repository::importGraph: librdf_new_uri failed", *this);
951 const boost::shared_ptr<librdf_parser> pParser(
952 librdf_new_parser(m_pWorld.get(), "rdfxml", NULL, NULL),
953 safe_librdf_free_parser);
954 if (!pParser) {
955 throw uno::RuntimeException(
956 "librdf_Repository::importGraph: "
957 "librdf_new_parser failed", *this);
960 uno::Sequence<sal_Int8> buf;
961 uno::Reference<io::XSeekable> xSeekable(i_xInStream, uno::UNO_QUERY);
962 // UGLY: if only that redland junk could read streams...
963 const sal_Int64 sz( xSeekable.is() ? xSeekable->getLength() : 1 << 20 );
964 // exceptions are propagated
965 i_xInStream->readBytes( buf, static_cast<sal_Int32>( sz ) );
966 const boost::shared_ptr<librdf_stream> pStream(
967 librdf_parser_parse_counted_string_as_stream(pParser.get(),
968 reinterpret_cast<const unsigned char*>(buf.getConstArray()),
969 buf.getLength(), pBaseURI.get()),
970 safe_librdf_free_stream);
971 if (!pStream) {
972 throw rdf::ParseException(
973 "librdf_Repository::importGraph: "
974 "librdf_parser_parse_counted_string_as_stream failed", *this);
976 m_NamedGraphs.insert(std::make_pair(contextU,
977 new librdf_NamedGraph(this, i_xGraphName)));
978 if (librdf_model_context_add_statements(m_pModel.get(),
979 pContext.get(), pStream.get())) {
980 throw rdf::RepositoryException(
981 "librdf_Repository::importGraph: "
982 "librdf_model_context_add_statements failed", *this);
984 return getGraph(i_xGraphName);
987 void addChaffWhenEncryptedStorage(const uno::Reference< io::XOutputStream > &rStream, unsigned char* pBuffer, size_t length)
989 if (!length)
990 return;
992 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(rStream,
993 uno::UNO_QUERY);
995 bool bAddChaff = xEncr.is() && xEncr->hasEncryptionData();
997 // exceptions are propagated
998 if (!bAddChaff)
1000 const uno::Sequence<sal_Int8> buf(
1001 reinterpret_cast<sal_Int8*>(pBuffer), length);
1002 rStream->writeBytes(buf);
1004 else
1006 unsigned char *postcomment =
1007 (unsigned char*)strchr((const char*)pBuffer, '\n');
1008 if (postcomment != NULL)
1010 ++postcomment;
1012 size_t preamblelen = postcomment - pBuffer;
1014 uno::Sequence<sal_Int8> buf(
1015 reinterpret_cast<sal_Int8*>(pBuffer), preamblelen);
1016 rStream->writeBytes(buf);
1018 rtl::OStringBuffer aComment;
1019 aComment.append("<!--");
1020 aComment.append(comphelper::xml::makeXMLChaff());
1021 aComment.append("-->");
1023 buf = uno::Sequence<sal_Int8>(
1024 reinterpret_cast<const sal_Int8*>(aComment.getStr()), aComment.getLength());
1025 rStream->writeBytes(buf);
1027 buf = uno::Sequence<sal_Int8>(
1028 reinterpret_cast<sal_Int8*>(postcomment), length-preamblelen);
1029 rStream->writeBytes(buf);
1034 void SAL_CALL
1035 librdf_Repository::exportGraph(::sal_Int16 i_Format,
1036 const uno::Reference< io::XOutputStream > & i_xOutStream,
1037 const uno::Reference< rdf::XURI > & i_xGraphName,
1038 const uno::Reference< rdf::XURI > & i_xBaseURI)
1039 throw (uno::RuntimeException, lang::IllegalArgumentException,
1040 datatransfer::UnsupportedFlavorException,
1041 container::NoSuchElementException, rdf::RepositoryException,
1042 io::IOException)
1044 ::osl::MutexGuard g(m_aMutex);
1045 if (!i_xOutStream.is()) {
1046 throw lang::IllegalArgumentException(
1047 "librdf_Repository::exportGraph: stream is null", *this, 1);
1049 // FIXME: other formats
1050 if (i_Format != rdf::FileFormat::RDF_XML) {
1051 throw datatransfer::UnsupportedFlavorException(
1052 "librdf_Repository::exportGraph: "
1053 "file format not supported", *this);
1055 if (!i_xGraphName.is()) {
1056 throw lang::IllegalArgumentException(
1057 "librdf_Repository::exportGraph: "
1058 "graph name is null", *this, 2);
1060 if (formatNeedsBaseURI(i_Format) && !i_xBaseURI.is()) {
1061 throw lang::IllegalArgumentException(
1062 "librdf_Repository::exportGraph: "
1063 "base URI is null", *this, 3);
1065 OSL_ENSURE(i_xBaseURI.is(), "no base uri");
1066 const ::rtl::OUString baseURIU( i_xBaseURI->getStringValue() );
1067 if (baseURIU.indexOf('#') >= 0) {
1068 throw lang::IllegalArgumentException(
1069 "librdf_Repository::exportGraph: "
1070 "base URI is not absolute", *this, 3);
1073 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1074 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1075 throw container::NoSuchElementException(
1076 "librdf_Repository::exportGraph: "
1077 "no graph with given URI exists", *this);
1079 const ::rtl::OString context(
1080 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1082 const boost::shared_ptr<librdf_node> pContext(
1083 librdf_new_node_from_uri_string(m_pWorld.get(),
1084 reinterpret_cast<const unsigned char*> (context.getStr())),
1085 safe_librdf_free_node);
1086 if (!pContext) {
1087 throw uno::RuntimeException(
1088 "librdf_Repository::exportGraph: "
1089 "librdf_new_node_from_uri_string failed", *this);
1091 const ::rtl::OString baseURI(
1092 ::rtl::OUStringToOString(baseURIU, RTL_TEXTENCODING_UTF8) );
1093 const boost::shared_ptr<librdf_uri> pBaseURI(
1094 librdf_new_uri(m_pWorld.get(),
1095 reinterpret_cast<const unsigned char*> (baseURI.getStr())),
1096 safe_librdf_free_uri);
1097 if (!pBaseURI) {
1098 throw uno::RuntimeException(
1099 "librdf_Repository::exportGraph: "
1100 "librdf_new_uri failed", *this);
1103 const boost::shared_ptr<librdf_stream> pStream(
1104 librdf_model_context_as_stream(m_pModel.get(), pContext.get()),
1105 safe_librdf_free_stream);
1106 if (!pStream) {
1107 throw rdf::RepositoryException(
1108 "librdf_Repository::exportGraph: "
1109 "librdf_model_context_as_stream failed", *this);
1111 const char *format("rdfxml");
1112 // #i116443#: abbrev breaks when certain URIs are used as data types
1113 // const char *format("rdfxml-abbrev");
1114 const boost::shared_ptr<librdf_serializer> pSerializer(
1115 librdf_new_serializer(m_pWorld.get(), format, NULL, NULL),
1116 safe_librdf_free_serializer);
1117 if (!pSerializer) {
1118 throw uno::RuntimeException(
1119 "librdf_Repository::exportGraph: "
1120 "librdf_new_serializer failed", *this);
1123 const boost::shared_ptr<librdf_uri> pRelativeURI(
1124 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1125 ("http://feature.librdf.org/raptor-relativeURIs")),
1126 safe_librdf_free_uri);
1127 const boost::shared_ptr<librdf_uri> pWriteBaseURI(
1128 librdf_new_uri(m_pWorld.get(), reinterpret_cast<const unsigned char*>
1129 ("http://feature.librdf.org/raptor-writeBaseURI")),
1130 safe_librdf_free_uri);
1131 const boost::shared_ptr<librdf_node> p0(
1132 librdf_new_node_from_literal(m_pWorld.get(),
1133 reinterpret_cast<const unsigned char*> ("0"), NULL, 0),
1134 safe_librdf_free_node);
1135 const boost::shared_ptr<librdf_node> p1(
1136 librdf_new_node_from_literal(m_pWorld.get(),
1137 reinterpret_cast<const unsigned char*> ("1"), NULL, 0),
1138 safe_librdf_free_node);
1139 if (!pWriteBaseURI || !pRelativeURI || !p0 || !p1) {
1140 throw uno::RuntimeException(
1141 "librdf_Repository::exportGraph: "
1142 "librdf_new_uri or librdf_new_node_from_literal failed", *this);
1145 // make URIs relative to base URI
1146 if (librdf_serializer_set_feature(pSerializer.get(),
1147 pRelativeURI.get(), p1.get()))
1149 throw uno::RuntimeException(
1150 "librdf_Repository::exportGraph: "
1151 "librdf_serializer_set_feature relativeURIs failed", *this);
1153 // but do not write the base URI to the file!
1154 if (librdf_serializer_set_feature(pSerializer.get(),
1155 pWriteBaseURI.get(), p0.get()))
1157 throw uno::RuntimeException(
1158 "librdf_Repository::exportGraph: "
1159 "librdf_serializer_set_feature writeBaseURI failed", *this);
1162 size_t length;
1163 const boost::shared_ptr<unsigned char> pBuf(
1164 librdf_serializer_serialize_stream_to_counted_string(
1165 pSerializer.get(), pBaseURI.get(), pStream.get(), &length), free);
1166 if (!pBuf) {
1167 throw rdf::RepositoryException(
1168 "librdf_Repository::exportGraph: "
1169 "librdf_serializer_serialize_stream_to_counted_string failed",
1170 *this);
1172 addChaffWhenEncryptedStorage(i_xOutStream, pBuf.get(), length);
1175 uno::Sequence< uno::Reference< rdf::XURI > > SAL_CALL
1176 librdf_Repository::getGraphNames()
1177 throw (uno::RuntimeException, rdf::RepositoryException)
1179 ::osl::MutexGuard g(m_aMutex);
1180 ::comphelper::SequenceAsVector< uno::Reference<rdf::XURI> > ret;
1181 std::transform(m_NamedGraphs.begin(), m_NamedGraphs.end(),
1182 std::back_inserter(ret),
1183 boost::bind(&rdf::XNamedGraph::getName,
1184 boost::bind(&NamedGraphMap_t::value_type::second, _1)));
1185 return ret.getAsConstList();
1188 uno::Reference< rdf::XNamedGraph > SAL_CALL
1189 librdf_Repository::getGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1190 throw (uno::RuntimeException, lang::IllegalArgumentException,
1191 rdf::RepositoryException)
1193 ::osl::MutexGuard g(m_aMutex);
1194 if (!i_xGraphName.is()) {
1195 throw lang::IllegalArgumentException(
1196 "librdf_Repository::getGraph: URI is null", *this, 0);
1198 const NamedGraphMap_t::iterator iter(
1199 m_NamedGraphs.find(i_xGraphName->getStringValue()) );
1200 if (iter != m_NamedGraphs.end()) {
1201 return uno::Reference<rdf::XNamedGraph>(iter->second.get());
1202 } else {
1203 return 0;
1207 uno::Reference< rdf::XNamedGraph > SAL_CALL
1208 librdf_Repository::createGraph(const uno::Reference< rdf::XURI > & i_xGraphName)
1209 throw (uno::RuntimeException, lang::IllegalArgumentException,
1210 container::ElementExistException, rdf::RepositoryException)
1212 ::osl::MutexGuard g(m_aMutex);
1213 if (!i_xGraphName.is()) {
1214 throw lang::IllegalArgumentException(
1215 "librdf_Repository::createGraph: URI is null", *this, 0);
1217 if (i_xGraphName->getStringValue().matchAsciiL(s_nsOOo, sizeof(s_nsOOo)-1))
1219 throw lang::IllegalArgumentException(
1220 "librdf_Repository::createGraph: URI is reserved", *this, 0);
1223 // NB: librdf does not have a concept of graphs as such;
1224 // a librdf named graph exists iff the model contains a statement with
1225 // the graph name as context
1226 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1227 if (m_NamedGraphs.find(contextU) != m_NamedGraphs.end()) {
1228 throw container::ElementExistException(
1229 "librdf_Repository::createGraph: graph with given URI exists", *this);
1231 m_NamedGraphs.insert(std::make_pair(contextU,
1232 new librdf_NamedGraph(this, i_xGraphName)));
1233 return uno::Reference<rdf::XNamedGraph>(
1234 m_NamedGraphs.find(contextU)->second.get());
1237 void SAL_CALL
1238 librdf_Repository::destroyGraph(
1239 const uno::Reference< rdf::XURI > & i_xGraphName)
1240 throw (uno::RuntimeException, lang::IllegalArgumentException,
1241 container::NoSuchElementException, rdf::RepositoryException)
1243 ::osl::MutexGuard g(m_aMutex);
1244 const NamedGraphMap_t::iterator iter( clearGraph(i_xGraphName) );
1245 m_NamedGraphs.erase(iter);
1248 static bool isMetadatableWithoutMetadata(
1249 uno::Reference<uno::XInterface> const & i_xNode)
1251 const uno::Reference<rdf::XMetadatable> xMeta( i_xNode, uno::UNO_QUERY );
1252 return (xMeta.is() && xMeta->getMetadataReference().Second.isEmpty());
1255 uno::Reference< container::XEnumeration > SAL_CALL
1256 librdf_Repository::getStatements(
1257 const uno::Reference< rdf::XResource > & i_xSubject,
1258 const uno::Reference< rdf::XURI > & i_xPredicate,
1259 const uno::Reference< rdf::XNode > & i_xObject)
1260 throw (uno::RuntimeException, rdf::RepositoryException)
1262 if (isMetadatableWithoutMetadata(i_xSubject) ||
1263 isMetadatableWithoutMetadata(i_xPredicate) ||
1264 isMetadatableWithoutMetadata(i_xObject))
1266 return new librdf_GraphResult(this, m_aMutex,
1267 ::boost::shared_ptr<librdf_stream>(),
1268 ::boost::shared_ptr<librdf_node>());
1271 ::osl::MutexGuard g(m_aMutex);
1272 const boost::shared_ptr<librdf_statement> pStatement(
1273 m_TypeConverter.mkStatement(m_pWorld.get(),
1274 i_xSubject, i_xPredicate, i_xObject),
1275 safe_librdf_free_statement);
1276 OSL_ENSURE(pStatement, "mkStatement failed");
1278 const boost::shared_ptr<librdf_stream> pStream(
1279 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1280 safe_librdf_free_stream);
1281 if (!pStream) {
1282 throw rdf::RepositoryException(
1283 "librdf_Repository::getStatements: "
1284 "librdf_model_find_statements failed", *this);
1287 return new librdf_GraphResult(this, m_aMutex, pStream,
1288 ::boost::shared_ptr<librdf_node>());
1292 uno::Reference< rdf::XQuerySelectResult > SAL_CALL
1293 librdf_Repository::querySelect(const ::rtl::OUString & i_rQuery)
1294 throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException)
1296 ::osl::MutexGuard g(m_aMutex);
1297 const ::rtl::OString query(
1298 ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1299 const boost::shared_ptr<librdf_query> pQuery(
1300 librdf_new_query(m_pWorld.get(), s_sparql, NULL,
1301 reinterpret_cast<const unsigned char*> (query.getStr()), NULL),
1302 safe_librdf_free_query);
1303 if (!pQuery) {
1304 throw rdf::QueryException(
1305 "librdf_Repository::querySelect: "
1306 "librdf_new_query failed", *this);
1308 const boost::shared_ptr<librdf_query_results> pResults(
1309 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1310 safe_librdf_free_query_results);
1311 if (!pResults || !librdf_query_results_is_bindings(pResults.get())) {
1312 throw rdf::QueryException(
1313 "librdf_Repository::querySelect: "
1314 "query result is null or not bindings", *this);
1317 const int count( librdf_query_results_get_bindings_count(pResults.get()) );
1318 if (count >= 0) {
1319 uno::Sequence< ::rtl::OUString > names(count);
1320 for (int i = 0; i < count; ++i) {
1321 const char* name( librdf_query_results_get_binding_name(
1322 pResults.get(), i) );
1323 if (!name) {
1324 throw rdf::QueryException(
1325 "librdf_Repository::querySelect: binding is null", *this);
1328 names[i] = ::rtl::OUString::createFromAscii(name);
1331 return new librdf_QuerySelectResult(this, m_aMutex,
1332 pQuery, pResults, names);
1334 } else {
1335 throw rdf::QueryException(
1336 "librdf_Repository::querySelect: "
1337 "librdf_query_results_get_bindings_count failed", *this);
1341 uno::Reference< container::XEnumeration > SAL_CALL
1342 librdf_Repository::queryConstruct(const ::rtl::OUString & i_rQuery)
1343 throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException)
1345 ::osl::MutexGuard g(m_aMutex);
1346 const ::rtl::OString query(
1347 ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1348 const boost::shared_ptr<librdf_query> pQuery(
1349 librdf_new_query(m_pWorld.get(), s_sparql, NULL,
1350 reinterpret_cast<const unsigned char*> (query.getStr()), NULL),
1351 safe_librdf_free_query);
1352 if (!pQuery) {
1353 throw rdf::QueryException(
1354 "librdf_Repository::queryConstruct: "
1355 "librdf_new_query failed", *this);
1357 const boost::shared_ptr<librdf_query_results> pResults(
1358 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1359 safe_librdf_free_query_results);
1360 if (!pResults || !librdf_query_results_is_graph(pResults.get())) {
1361 throw rdf::QueryException(
1362 "librdf_Repository::queryConstruct: "
1363 "query result is null or not graph", *this);
1365 const boost::shared_ptr<librdf_stream> pStream(
1366 librdf_query_results_as_stream(pResults.get()),
1367 safe_librdf_free_stream);
1368 if (!pStream) {
1369 throw rdf::QueryException(
1370 "librdf_Repository::queryConstruct: "
1371 "librdf_query_results_as_stream failed", *this);
1374 return new librdf_GraphResult(this, m_aMutex, pStream,
1375 ::boost::shared_ptr<librdf_node>(), pQuery);
1378 ::sal_Bool SAL_CALL
1379 librdf_Repository::queryAsk(const ::rtl::OUString & i_rQuery)
1380 throw (uno::RuntimeException, rdf::QueryException, rdf::RepositoryException)
1382 ::osl::MutexGuard g(m_aMutex);
1384 const ::rtl::OString query(
1385 ::rtl::OUStringToOString(i_rQuery, RTL_TEXTENCODING_UTF8) );
1386 const boost::shared_ptr<librdf_query> pQuery(
1387 librdf_new_query(m_pWorld.get(), s_sparql, NULL,
1388 reinterpret_cast<const unsigned char*> (query.getStr()), NULL),
1389 safe_librdf_free_query);
1390 if (!pQuery) {
1391 throw rdf::QueryException(
1392 "librdf_Repository::queryAsk: "
1393 "librdf_new_query failed", *this);
1395 const boost::shared_ptr<librdf_query_results> pResults(
1396 librdf_model_query_execute(m_pModel.get(), pQuery.get()),
1397 safe_librdf_free_query_results);
1398 if (!pResults || !librdf_query_results_is_boolean(pResults.get())) {
1399 throw rdf::QueryException(
1400 "librdf_Repository::queryAsk: "
1401 "query result is null or not boolean", *this);
1403 return librdf_query_results_get_boolean(pResults.get())
1404 ? sal_True : sal_False;
1407 // ::com::sun::star::rdf::XDocumentRepository:
1408 void SAL_CALL librdf_Repository::setStatementRDFa(
1409 const uno::Reference< rdf::XResource > & i_xSubject,
1410 const uno::Sequence< uno::Reference< rdf::XURI > > & i_rPredicates,
1411 const uno::Reference< rdf::XMetadatable > & i_xObject,
1412 const ::rtl::OUString & i_rRDFaContent,
1413 const uno::Reference< rdf::XURI > & i_xRDFaDatatype)
1414 throw (uno::RuntimeException, lang::IllegalArgumentException,
1415 rdf::RepositoryException)
1417 static const ::rtl::OUString s_cell("com.sun.star.table.Cell");
1418 static const ::rtl::OUString s_cellprops("com.sun.star.text.CellProperties"); // for writer
1419 static const ::rtl::OUString s_paragraph("com.sun.star.text.Paragraph");
1420 static const ::rtl::OUString s_bookmark("com.sun.star.text.Bookmark");
1421 static const ::rtl::OUString s_meta("com.sun.star.text.InContentMetadata");
1423 if (!i_xSubject.is()) {
1424 throw lang::IllegalArgumentException(
1425 "librdf_Repository::setStatementRDFa: Subject is null", *this, 0);
1427 if (!i_rPredicates.getLength()) {
1428 throw lang::IllegalArgumentException(
1429 "librdf_Repository::setStatementRDFa: no Predicates",
1430 *this, 1);
1432 for (sal_Int32 i = 0; i < i_rPredicates.getLength(); ++i) {
1433 if (!i_rPredicates[i].is()) {
1434 throw lang::IllegalArgumentException(
1435 "librdf_Repository::setStatementRDFa: Predicate is null",
1436 *this, 1);
1439 if (!i_xObject.is()) {
1440 throw lang::IllegalArgumentException(
1441 "librdf_Repository::setStatementRDFa: Object is null", *this, 2);
1443 const uno::Reference<lang::XServiceInfo> xService(i_xObject,
1444 uno::UNO_QUERY_THROW);
1445 uno::Reference<text::XTextRange> xTextRange;
1446 if (xService->supportsService(s_cell) ||
1447 xService->supportsService(s_cellprops) ||
1448 xService->supportsService(s_paragraph))
1450 xTextRange.set(i_xObject, uno::UNO_QUERY_THROW);
1452 else if (xService->supportsService(s_bookmark) ||
1453 xService->supportsService(s_meta))
1455 const uno::Reference<text::XTextContent> xTextContent(i_xObject,
1456 uno::UNO_QUERY_THROW);
1457 xTextRange = xTextContent->getAnchor();
1459 if (!xTextRange.is()) {
1460 throw lang::IllegalArgumentException(
1461 "librdf_Repository::setStatementRDFa: "
1462 "Object does not support RDFa", *this, 2);
1464 // ensure that the metadatable has an XML ID
1465 i_xObject->ensureMetadataReference();
1466 const beans::StringPair mdref( i_xObject->getMetadataReference() );
1467 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1468 throw uno::RuntimeException(
1469 "librdf_Repository::setStatementRDFa: "
1470 "ensureMetadataReference did not", *this);
1472 ::rtl::OUString const sXmlId(mdref.First + "#" + mdref.Second);
1473 uno::Reference<rdf::XURI> xXmlId;
1474 try {
1475 xXmlId.set( rdf::URI::create(m_xContext,
1476 ::rtl::OUString::createFromAscii(s_nsOOo) + sXmlId),
1477 uno::UNO_QUERY_THROW);
1478 } catch (const lang::IllegalArgumentException & iae) {
1479 throw lang::WrappedTargetRuntimeException(
1480 "librdf_Repository::setStatementRDFa: "
1481 "cannot create URI for XML ID", *this, uno::makeAny(iae));
1484 ::osl::MutexGuard g(m_aMutex);
1485 ::rtl::OUString const content( (i_rRDFaContent.isEmpty())
1486 ? xTextRange->getString()
1487 : i_rRDFaContent );
1488 uno::Reference<rdf::XNode> xContent;
1489 try {
1490 if (i_xRDFaDatatype.is()) {
1491 xContent.set(rdf::Literal::createWithType(m_xContext,
1492 content, i_xRDFaDatatype),
1493 uno::UNO_QUERY_THROW);
1494 } else {
1495 xContent.set(rdf::Literal::create(m_xContext, content),
1496 uno::UNO_QUERY_THROW);
1498 } catch (const lang::IllegalArgumentException & iae) {
1499 throw lang::WrappedTargetRuntimeException(
1500 "librdf_Repository::setStatementRDFa: "
1501 "cannot create literal", *this, uno::makeAny(iae));
1503 removeStatementRDFa(i_xObject);
1504 if (i_rRDFaContent.isEmpty()) {
1505 m_RDFaXHTMLContentSet.erase(sXmlId);
1506 } else {
1507 m_RDFaXHTMLContentSet.insert(sXmlId);
1509 ::std::for_each(::comphelper::stl_begin(i_rPredicates),
1510 ::comphelper::stl_end(i_rPredicates),
1511 ::boost::bind( &librdf_Repository::addStatementGraph,
1512 this, i_xSubject, _1, xContent, xXmlId, true));
1515 void SAL_CALL librdf_Repository::removeStatementRDFa(
1516 const uno::Reference< rdf::XMetadatable > & i_xElement)
1517 throw (uno::RuntimeException, lang::IllegalArgumentException,
1518 rdf::RepositoryException)
1520 if (!i_xElement.is()) {
1521 throw lang::IllegalArgumentException(
1522 "librdf_Repository::removeStatementRDFa: Element is null",
1523 *this, 0);
1526 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1527 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1528 return; // nothing to do...
1530 uno::Reference<rdf::XURI> xXmlId;
1531 try {
1532 xXmlId.set( rdf::URI::create(m_xContext,
1533 ::rtl::OUString::createFromAscii(s_nsOOo)
1534 + mdref.First + "#"
1535 + mdref.Second),
1536 uno::UNO_QUERY_THROW);
1537 } catch (const lang::IllegalArgumentException & iae) {
1538 throw lang::WrappedTargetRuntimeException(
1539 "librdf_Repository::removeStatementRDFa: "
1540 "cannot create URI for XML ID", *this, uno::makeAny(iae));
1542 // clearGraph does locking, not needed here
1543 clearGraph(xXmlId, true);
1546 beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool > SAL_CALL
1547 librdf_Repository::getStatementRDFa(
1548 const uno::Reference< rdf::XMetadatable > & i_xElement)
1549 throw (uno::RuntimeException, lang::IllegalArgumentException,
1550 rdf::RepositoryException)
1552 if (!i_xElement.is()) {
1553 throw lang::IllegalArgumentException(
1554 "librdf_Repository::getStatementRDFa: Element is null", *this, 0);
1556 const beans::StringPair mdref( i_xElement->getMetadataReference() );
1557 if ((mdref.First.isEmpty()) || (mdref.Second.isEmpty())) {
1558 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >();
1560 ::rtl::OUString const sXmlId(mdref.First + "#" + mdref.Second);
1561 uno::Reference<rdf::XURI> xXmlId;
1562 try {
1563 xXmlId.set( rdf::URI::create(m_xContext,
1564 ::rtl::OUString::createFromAscii(s_nsOOo) + sXmlId),
1565 uno::UNO_QUERY_THROW);
1566 } catch (const lang::IllegalArgumentException & iae) {
1567 throw lang::WrappedTargetRuntimeException(
1568 "librdf_Repository::getStatementRDFa: "
1569 "cannot create URI for XML ID", *this, uno::makeAny(iae));
1572 ::osl::MutexGuard g(m_aMutex);
1573 ::comphelper::SequenceAsVector< rdf::Statement > ret;
1574 const uno::Reference<container::XEnumeration> xIter(
1575 getStatementsGraph(0, 0, 0, xXmlId, true) );
1576 OSL_ENSURE(xIter.is(), "getStatementRDFa: no result?");
1577 if (!xIter.is()) throw uno::RuntimeException();
1578 while (xIter->hasMoreElements()) {
1579 rdf::Statement stmt;
1580 if (!(xIter->nextElement() >>= stmt)) {
1581 OSL_FAIL("getStatementRDFa: result of wrong type?");
1582 } else {
1583 ret.push_back(stmt);
1586 return beans::Pair< uno::Sequence<rdf::Statement>, sal_Bool >(
1587 ret.getAsConstList(), 0 != m_RDFaXHTMLContentSet.count(sXmlId));
1590 extern "C"
1591 librdf_statement *rdfa_context_stream_map_handler(
1592 librdf_stream *i_pStream, void *, librdf_statement *i_pStatement)
1594 OSL_ENSURE(i_pStream, "rdfa_context_stream_map_handler: stream null");
1595 if (i_pStream) {
1596 SAL_WNODEPRECATED_DECLARATIONS_PUSH;
1597 librdf_node *pCtxt( static_cast<librdf_node *>
1598 (librdf_stream_get_context(i_pStream)) );
1599 SAL_WNODEPRECATED_DECLARATIONS_POP;
1600 OSL_ENSURE(pCtxt, "rdfa_context_stream_map_handler: context null");
1601 if (pCtxt && isInternalContext(pCtxt)) {
1602 return i_pStatement;
1605 return 0;
1608 uno::Reference< container::XEnumeration > SAL_CALL
1609 librdf_Repository::getStatementsRDFa(
1610 const uno::Reference< rdf::XResource > & i_xSubject,
1611 const uno::Reference< rdf::XURI > & i_xPredicate,
1612 const uno::Reference< rdf::XNode > & i_xObject)
1613 throw (uno::RuntimeException, rdf::RepositoryException)
1615 if (isMetadatableWithoutMetadata(i_xSubject) ||
1616 isMetadatableWithoutMetadata(i_xPredicate) ||
1617 isMetadatableWithoutMetadata(i_xObject))
1619 return new librdf_GraphResult(this, m_aMutex,
1620 ::boost::shared_ptr<librdf_stream>(),
1621 ::boost::shared_ptr<librdf_node>());
1624 ::osl::MutexGuard g(m_aMutex);
1625 const boost::shared_ptr<librdf_statement> pStatement(
1626 m_TypeConverter.mkStatement(m_pWorld.get(),
1627 i_xSubject, i_xPredicate, i_xObject),
1628 safe_librdf_free_statement);
1629 OSL_ENSURE(pStatement, "mkStatement failed");
1631 const boost::shared_ptr<librdf_stream> pStream(
1632 librdf_model_find_statements(m_pModel.get(), pStatement.get()),
1633 safe_librdf_free_stream);
1634 if (!pStream) {
1635 throw rdf::RepositoryException(
1636 "librdf_Repository::getStatementsRDFa: "
1637 "librdf_model_find_statements failed", *this);
1640 if (librdf_stream_add_map(pStream.get(), rdfa_context_stream_map_handler,
1641 0, 0)) {
1642 throw rdf::RepositoryException(
1643 "librdf_Repository::getStatementsRDFa: "
1644 "librdf_stream_add_map failed", *this);
1647 return new librdf_GraphResult(this, m_aMutex, pStream,
1648 ::boost::shared_ptr<librdf_node>());
1651 // ::com::sun::star::lang::XInitialization:
1652 void SAL_CALL librdf_Repository::initialize(
1653 const uno::Sequence< ::com::sun::star::uno::Any > & i_rArguments)
1654 throw (uno::RuntimeException, uno::Exception)
1656 (void) i_rArguments;
1658 ::osl::MutexGuard g(m_aMutex);
1660 // m_pWorld.reset(m_TypeConverter.createWorld(), safe_librdf_free_world);
1661 m_pStorage.reset(m_TypeConverter.createStorage(m_pWorld.get()),
1662 safe_librdf_free_storage);
1663 m_pModel.reset(m_TypeConverter.createModel(
1664 m_pWorld.get(), m_pStorage.get()), safe_librdf_free_model);
1667 const NamedGraphMap_t::iterator SAL_CALL librdf_Repository::clearGraph(
1668 const uno::Reference< rdf::XURI > & i_xGraphName, bool i_Internal)
1669 // throw (uno::RuntimeException, container::NoSuchElementException,
1670 // rdf::RepositoryException)
1672 if (!i_xGraphName.is()) {
1673 throw lang::IllegalArgumentException(
1674 "librdf_Repository::clearGraph: URI is null", *this, 0);
1676 ::osl::MutexGuard g(m_aMutex);
1677 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1678 const NamedGraphMap_t::iterator iter( m_NamedGraphs.find(contextU) );
1679 if (!i_Internal && iter == m_NamedGraphs.end()) {
1680 throw container::NoSuchElementException(
1681 "librdf_Repository::clearGraph: "
1682 "no graph with given URI exists", *this);
1684 const ::rtl::OString context(
1685 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1687 const boost::shared_ptr<librdf_node> pContext(
1688 librdf_new_node_from_uri_string(m_pWorld.get(),
1689 reinterpret_cast<const unsigned char*> (context.getStr())),
1690 safe_librdf_free_node);
1691 if (!pContext) {
1692 throw uno::RuntimeException(
1693 "librdf_Repository::clearGraph: "
1694 "librdf_new_node_from_uri_string failed", *this);
1696 if (librdf_model_context_remove_statements(m_pModel.get(), pContext.get()))
1698 throw rdf::RepositoryException(
1699 "librdf_Repository::clearGraph: "
1700 "librdf_model_context_remove_statements failed", *this);
1702 return iter;
1705 void librdf_Repository::addStatementGraph(
1706 const uno::Reference< rdf::XResource > & i_xSubject,
1707 const uno::Reference< rdf::XURI > & i_xPredicate,
1708 const uno::Reference< rdf::XNode > & i_xObject,
1709 const uno::Reference< rdf::XURI > & i_xGraphName,
1710 bool i_Internal)
1711 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1712 // container::NoSuchElementException, rdf::RepositoryException)
1714 if (!i_xSubject.is()) {
1715 throw lang::IllegalArgumentException(
1716 "librdf_Repository::addStatement: Subject is null", *this, 0);
1718 if (!i_xPredicate.is()) {
1719 throw lang::IllegalArgumentException(
1720 "librdf_Repository::addStatement: Predicate is null",
1721 *this, 1);
1723 if (!i_xObject.is()) {
1724 throw lang::IllegalArgumentException(
1725 "librdf_Repository::addStatement: Object is null", *this, 2);
1728 ::osl::MutexGuard g(m_aMutex);
1729 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1730 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1731 throw container::NoSuchElementException(
1732 "librdf_Repository::addStatement: "
1733 "no graph with given URI exists", *this);
1735 const ::rtl::OString context(
1736 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1738 const boost::shared_ptr<librdf_node> pContext(
1739 librdf_new_node_from_uri_string(m_pWorld.get(),
1740 reinterpret_cast<const unsigned char*> (context.getStr())),
1741 safe_librdf_free_node);
1742 if (!pContext) {
1743 throw uno::RuntimeException(
1744 "librdf_Repository::addStatement: "
1745 "librdf_new_node_from_uri_string failed", *this);
1747 const boost::shared_ptr<librdf_statement> pStatement(
1748 m_TypeConverter.mkStatement(m_pWorld.get(),
1749 i_xSubject, i_xPredicate, i_xObject),
1750 safe_librdf_free_statement);
1751 OSL_ENSURE(pStatement, "mkStatement failed");
1753 // Test for duplicate statement
1754 // librdf_model_add_statement disallows duplicates while
1755 // librdf_model_context_add_statement allows duplicates
1757 const boost::shared_ptr<librdf_stream> pStream(
1758 librdf_model_find_statements_in_context(m_pModel.get(),
1759 pStatement.get(), pContext.get()),
1760 safe_librdf_free_stream);
1761 if (pStream && !librdf_stream_end(pStream.get()))
1762 return;
1765 if (librdf_model_context_add_statement(m_pModel.get(),
1766 pContext.get(), pStatement.get())) {
1767 throw rdf::RepositoryException(
1768 "librdf_Repository::addStatement: "
1769 "librdf_model_context_add_statement failed", *this);
1773 void librdf_Repository::removeStatementsGraph(
1774 const uno::Reference< rdf::XResource > & i_xSubject,
1775 const uno::Reference< rdf::XURI > & i_xPredicate,
1776 const uno::Reference< rdf::XNode > & i_xObject,
1777 const uno::Reference< rdf::XURI > & i_xGraphName)
1778 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1779 // container::NoSuchElementException, rdf::RepositoryException)
1781 if (isMetadatableWithoutMetadata(i_xSubject) ||
1782 isMetadatableWithoutMetadata(i_xPredicate) ||
1783 isMetadatableWithoutMetadata(i_xObject))
1785 return;
1788 ::osl::MutexGuard g(m_aMutex);
1789 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1790 if (m_NamedGraphs.find(contextU) == m_NamedGraphs.end()) {
1791 throw container::NoSuchElementException(
1792 "librdf_Repository::removeStatements: "
1793 "no graph with given URI exists", *this);
1795 const ::rtl::OString context(
1796 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1798 const boost::shared_ptr<librdf_node> pContext(
1799 librdf_new_node_from_uri_string(m_pWorld.get(),
1800 reinterpret_cast<const unsigned char*> (context.getStr())),
1801 safe_librdf_free_node);
1802 if (!pContext) {
1803 throw uno::RuntimeException(
1804 "librdf_Repository::removeStatements: "
1805 "librdf_new_node_from_uri_string failed", *this);
1807 const boost::shared_ptr<librdf_statement> pStatement(
1808 m_TypeConverter.mkStatement(m_pWorld.get(),
1809 i_xSubject, i_xPredicate, i_xObject),
1810 safe_librdf_free_statement);
1811 OSL_ENSURE(pStatement, "mkStatement failed");
1813 const boost::shared_ptr<librdf_stream> pStream(
1814 librdf_model_find_statements_in_context(m_pModel.get(),
1815 pStatement.get(), pContext.get()),
1816 safe_librdf_free_stream);
1817 if (!pStream) {
1818 throw rdf::RepositoryException(
1819 "librdf_Repository::removeStatements: "
1820 "librdf_model_find_statements_in_context failed", *this);
1823 if (!librdf_stream_end(pStream.get())) {
1824 do {
1825 librdf_statement *pStmt( librdf_stream_get_object(pStream.get()) );
1826 if (!pStmt) {
1827 throw rdf::RepositoryException(
1828 "librdf_Repository::removeStatements: "
1829 "librdf_stream_get_object failed", *this);
1831 if (librdf_model_context_remove_statement(m_pModel.get(),
1832 pContext.get(), pStmt)) {
1833 throw rdf::RepositoryException(
1834 "librdf_Repository::removeStatements: "
1835 "librdf_model_context_remove_statement failed", *this);
1837 } while (!librdf_stream_next(pStream.get()));
1841 uno::Reference< container::XEnumeration >
1842 librdf_Repository::getStatementsGraph(
1843 const uno::Reference< rdf::XResource > & i_xSubject,
1844 const uno::Reference< rdf::XURI > & i_xPredicate,
1845 const uno::Reference< rdf::XNode > & i_xObject,
1846 const uno::Reference< rdf::XURI > & i_xGraphName,
1847 bool i_Internal)
1848 //throw (uno::RuntimeException, lang::IllegalArgumentException,
1849 // container::NoSuchElementException, rdf::RepositoryException)
1851 // N.B.: if any of subject, predicate, object is an XMetadatable, and
1852 // has no metadata reference, then there cannot be any node in the graph
1853 // representing it; in order to prevent side effect
1854 // (ensureMetadataReference), check for this condition and return
1855 if (isMetadatableWithoutMetadata(i_xSubject) ||
1856 isMetadatableWithoutMetadata(i_xPredicate) ||
1857 isMetadatableWithoutMetadata(i_xObject))
1859 return new librdf_GraphResult(this, m_aMutex,
1860 ::boost::shared_ptr<librdf_stream>(),
1861 ::boost::shared_ptr<librdf_node>());
1864 ::osl::MutexGuard g(m_aMutex);
1865 const ::rtl::OUString contextU( i_xGraphName->getStringValue() );
1866 if (!i_Internal && (m_NamedGraphs.find(contextU) == m_NamedGraphs.end())) {
1867 throw container::NoSuchElementException(
1868 "librdf_Repository::getStatements: "
1869 "no graph with given URI exists", *this);
1871 const ::rtl::OString context(
1872 ::rtl::OUStringToOString(contextU, RTL_TEXTENCODING_UTF8) );
1874 const boost::shared_ptr<librdf_node> pContext(
1875 librdf_new_node_from_uri_string(m_pWorld.get(),
1876 reinterpret_cast<const unsigned char*> (context.getStr())),
1877 safe_librdf_free_node);
1878 if (!pContext) {
1879 throw uno::RuntimeException(
1880 "librdf_Repository::getStatements: "
1881 "librdf_new_node_from_uri_string failed", *this);
1883 const boost::shared_ptr<librdf_statement> pStatement(
1884 m_TypeConverter.mkStatement(m_pWorld.get(),
1885 i_xSubject, i_xPredicate, i_xObject),
1886 safe_librdf_free_statement);
1887 OSL_ENSURE(pStatement, "mkStatement failed");
1889 const boost::shared_ptr<librdf_stream> pStream(
1890 librdf_model_find_statements_in_context(m_pModel.get(),
1891 pStatement.get(), pContext.get()),
1892 safe_librdf_free_stream);
1893 if (!pStream) {
1894 throw rdf::RepositoryException(
1895 "librdf_Repository::getStatements: "
1896 "librdf_model_find_statements_in_context failed", *this);
1899 // librdf_model_find_statements_in_context is buggy and does not put
1900 // the context into result statements; pass it to librdf_GraphResult here
1901 return new librdf_GraphResult(this, m_aMutex, pStream, pContext);
1904 librdf_world *librdf_TypeConverter::createWorld() const
1906 // create and initialize world
1907 librdf_world *pWorld( librdf_new_world() );
1908 if (!pWorld) {
1909 throw uno::RuntimeException(
1910 "librdf_TypeConverter::createWorld: librdf_new_world failed",
1911 m_rRep);
1913 //FIXME logger, digest, features?
1914 xsltSecurityPrefsPtr origprefs = xsltGetDefaultSecurityPrefs();
1915 librdf_world_open(pWorld);
1916 xsltSecurityPrefsPtr newprefs = xsltGetDefaultSecurityPrefs();
1917 if (newprefs != origprefs) {
1918 // #i110523# restore libxslt global configuration
1919 // (gratuitously overwritten by raptor_init_parser_grddl_common)
1920 // (this is the only reason unordf is linked against libxslt)
1921 xsltSetDefaultSecurityPrefs(origprefs);
1923 return pWorld;
1926 librdf_storage *
1927 librdf_TypeConverter::createStorage(librdf_world *i_pWorld) const
1929 librdf_storage *pStorage(
1930 // librdf_new_storage(i_pWorld, "memory", NULL, "contexts='yes'") );
1931 librdf_new_storage(i_pWorld, "hashes", NULL,
1932 "contexts='yes',hash-type='memory'") );
1933 if (!pStorage) {
1934 throw uno::RuntimeException(
1935 "librdf_TypeConverter::createStorage: librdf_new_storage failed",
1936 m_rRep);
1938 return pStorage;
1941 librdf_model *librdf_TypeConverter::createModel(
1942 librdf_world *i_pWorld, librdf_storage * i_pStorage) const
1944 librdf_model *pRepository( librdf_new_model(i_pWorld, i_pStorage, NULL) );
1945 if (!pRepository) {
1946 throw uno::RuntimeException(
1947 "librdf_TypeConverter::createModel: librdf_new_model failed",
1948 m_rRep);
1950 //FIXME
1951 #if 0
1953 librdf_uri * ctxt = librdf_new_uri(i_pWorld, reinterpret_cast<const unsigned char *>(LIBRDF_MODEL_FEATURE_CONTEXTS));
1954 librdf_node * contexts = librdf_model_get_feature(repository, ctxt);
1955 if (!contexts)
1956 throw;
1957 std::cout << "value of contexts feature: ";
1958 prtNode(contexts);
1959 std::cout << std::endl;
1960 // librdf_model_set_feature(repository, LIBRDF_FEATURE_CONTEXTS, ...);
1961 safe_librdf_free_node(contexts);
1962 safe_librdf_free_uri(ctxt);
1964 #endif
1965 return pRepository;
1968 // this does NOT create a node, only URI
1969 librdf_uri* librdf_TypeConverter::mkURI( librdf_world* i_pWorld,
1970 const uno::Reference< rdf::XURI > & i_xURI) const
1972 const ::rtl::OString uri(
1973 ::rtl::OUStringToOString(i_xURI->getStringValue(),
1974 RTL_TEXTENCODING_UTF8) );
1975 librdf_uri *pURI( librdf_new_uri(i_pWorld,
1976 reinterpret_cast<const unsigned char *>(uri.getStr())));
1977 if (!pURI) {
1978 throw uno::RuntimeException(
1979 "librdf_TypeConverter::mkURI: librdf_new_uri failed", 0);
1981 return pURI;
1984 // create blank or URI node
1985 librdf_node* librdf_TypeConverter::mkResource( librdf_world* i_pWorld,
1986 const uno::Reference< rdf::XResource > & i_xResource) const
1988 if (!i_xResource.is()) return 0;
1989 uno::Reference< rdf::XBlankNode > xBlankNode(i_xResource, uno::UNO_QUERY);
1990 if (xBlankNode.is()) {
1991 const ::rtl::OString label(
1992 ::rtl::OUStringToOString(xBlankNode->getStringValue(),
1993 RTL_TEXTENCODING_UTF8) );
1994 librdf_node *pNode(
1995 librdf_new_node_from_blank_identifier(i_pWorld,
1996 reinterpret_cast<const unsigned char*> (label.getStr())));
1997 if (!pNode) {
1998 throw uno::RuntimeException(
1999 "librdf_TypeConverter::mkResource: "
2000 "librdf_new_node_from_blank_identifier failed", 0);
2002 return pNode;
2003 } else { // assumption: everything else is URI
2004 const ::rtl::OString uri(
2005 ::rtl::OUStringToOString(i_xResource->getStringValue(),
2006 RTL_TEXTENCODING_UTF8) );
2007 librdf_node *pNode(
2008 librdf_new_node_from_uri_string(i_pWorld,
2009 reinterpret_cast<const unsigned char*> (uri.getStr())));
2010 if (!pNode) {
2011 throw uno::RuntimeException(
2012 "librdf_TypeConverter::mkResource: "
2013 "librdf_new_node_from_uri_string failed", 0);
2015 return pNode;
2019 // create blank or URI or literal node
2020 librdf_node* librdf_TypeConverter::mkNode( librdf_world* i_pWorld,
2021 const uno::Reference< rdf::XNode > & i_xNode) const
2023 if (!i_xNode.is()) return 0;
2024 uno::Reference< rdf::XResource > xResource(i_xNode, uno::UNO_QUERY);
2025 if (xResource.is()) {
2026 return mkResource(i_pWorld, xResource);
2028 uno::Reference< rdf::XLiteral> xLiteral(i_xNode, uno::UNO_QUERY);
2029 OSL_ENSURE(xLiteral.is(),
2030 "mkNode: someone invented a new rdf.XNode and did not tell me");
2031 if (!xLiteral.is()) return 0;
2032 const ::rtl::OString val(
2033 ::rtl::OUStringToOString(xLiteral->getValue(),
2034 RTL_TEXTENCODING_UTF8) );
2035 const ::rtl::OString lang(
2036 ::rtl::OUStringToOString(xLiteral->getLanguage(),
2037 RTL_TEXTENCODING_UTF8) );
2038 const uno::Reference< rdf::XURI > xType(xLiteral->getDatatype());
2039 librdf_node * ret(0);
2040 if (lang.isEmpty()) {
2041 if (!xType.is()) {
2042 ret = librdf_new_node_from_literal(i_pWorld,
2043 reinterpret_cast<const unsigned char*> (val.getStr()),
2044 NULL, 0);
2045 } else {
2046 const boost::shared_ptr<librdf_uri> pDatatype(
2047 mkURI(i_pWorld, xType), safe_librdf_free_uri);
2048 ret = librdf_new_node_from_typed_literal(i_pWorld,
2049 reinterpret_cast<const unsigned char*> (val.getStr()),
2050 NULL, pDatatype.get());
2052 } else {
2053 if (!xType.is()) {
2054 ret = librdf_new_node_from_literal(i_pWorld,
2055 reinterpret_cast<const unsigned char*> (val.getStr()),
2056 (lang.getStr()), 0);
2058 } else {
2059 OSL_FAIL("mkNode: invalid literal");
2060 return 0;
2063 if (!ret) {
2064 throw uno::RuntimeException(
2065 "librdf_TypeConverter::mkNode: librdf_new_node_from_literal failed", 0);
2067 return ret;
2070 librdf_statement* librdf_TypeConverter::mkStatement( librdf_world* i_pWorld,
2071 const uno::Reference< rdf::XResource > & i_xSubject,
2072 const uno::Reference< rdf::XURI > & i_xPredicate,
2073 const uno::Reference< rdf::XNode > & i_xObject) const
2075 librdf_node* pSubject( mkResource(i_pWorld, i_xSubject) );
2076 librdf_node* pPredicate(0);
2077 librdf_node* pObject(0);
2078 try {
2079 const uno::Reference<rdf::XResource> xPredicate(i_xPredicate,
2080 uno::UNO_QUERY);
2081 pPredicate = mkResource(i_pWorld, xPredicate);
2082 try {
2083 pObject = mkNode(i_pWorld, i_xObject);
2084 } catch (...) {
2085 safe_librdf_free_node(pPredicate);
2086 throw;
2088 } catch (...) {
2089 safe_librdf_free_node(pSubject);
2090 throw;
2092 // NB: this takes ownership of the nodes! (which is really ugly)
2093 librdf_statement* pStatement( librdf_new_statement_from_nodes(i_pWorld,
2094 pSubject, pPredicate, pObject) );
2095 if (!pStatement) {
2096 throw uno::RuntimeException(
2097 "librdf_TypeConverter::mkStatement: "
2098 "librdf_new_statement_from_nodes failed", 0);
2100 return pStatement;
2103 uno::Reference<rdf::XURI>
2104 librdf_TypeConverter::convertToXURI(librdf_uri* i_pURI) const
2106 if (!i_pURI) return 0;
2107 const unsigned char* uri( librdf_uri_as_string(i_pURI) );
2108 if (!uri) {
2109 throw uno::RuntimeException(
2110 "librdf_TypeConverter::convertToXURI: "
2111 "librdf_uri_as_string failed", m_rRep);
2113 ::rtl::OUString uriU( ::rtl::OStringToOUString(
2114 ::rtl::OString(reinterpret_cast<const sal_Char*>(uri)),
2115 RTL_TEXTENCODING_UTF8) );
2116 try {
2117 return rdf::URI::create(m_xContext, uriU);
2118 } catch (const lang::IllegalArgumentException & iae) {
2119 throw lang::WrappedTargetRuntimeException(
2120 "librdf_TypeConverter::convertToXURI: "
2121 "illegal uri", m_rRep, uno::makeAny(iae));
2125 uno::Reference<rdf::XURI>
2126 librdf_TypeConverter::convertToXURI(librdf_node* i_pNode) const
2128 if (!i_pNode) return 0;
2129 if (librdf_node_is_resource(i_pNode)) {
2130 librdf_uri* pURI( librdf_node_get_uri(i_pNode) );
2131 if (!pURI) {
2132 throw uno::RuntimeException(
2133 "librdf_TypeConverter::convertToXURI: "
2134 "resource has no uri", m_rRep);
2136 return convertToXURI(pURI);
2137 } else {
2138 OSL_FAIL("convertToXURI: unknown librdf_node");
2139 return 0;
2143 uno::Reference<rdf::XResource>
2144 librdf_TypeConverter::convertToXResource(librdf_node* i_pNode) const
2146 if (!i_pNode) return 0;
2147 if (librdf_node_is_blank(i_pNode)) {
2148 const unsigned char* label( librdf_node_get_blank_identifier(i_pNode) );
2149 if (!label) {
2150 throw uno::RuntimeException(
2151 "librdf_TypeConverter::convertToXResource: "
2152 "blank node has no label", m_rRep);
2154 ::rtl::OUString labelU( ::rtl::OStringToOUString(
2155 ::rtl::OString(reinterpret_cast<const sal_Char*>(label)),
2156 RTL_TEXTENCODING_UTF8) );
2157 try {
2158 return uno::Reference<rdf::XResource>(
2159 rdf::BlankNode::create(m_xContext, labelU), uno::UNO_QUERY);
2160 } catch (const lang::IllegalArgumentException & iae) {
2161 throw lang::WrappedTargetRuntimeException(
2162 "librdf_TypeConverter::convertToXResource: "
2163 "illegal blank node label", m_rRep, uno::makeAny(iae));
2165 } else {
2166 return uno::Reference<rdf::XResource>(convertToXURI(i_pNode),
2167 uno::UNO_QUERY);
2171 uno::Reference<rdf::XNode>
2172 librdf_TypeConverter::convertToXNode(librdf_node* i_pNode) const
2174 if (!i_pNode) return 0;
2175 if (!librdf_node_is_literal(i_pNode)) {
2176 return uno::Reference<rdf::XNode>(convertToXResource(i_pNode),
2177 uno::UNO_QUERY);
2179 const unsigned char* value( librdf_node_get_literal_value(i_pNode) );
2180 if (!value) {
2181 throw uno::RuntimeException(
2182 "librdf_TypeConverter::convertToXNode: "
2183 "literal has no value", m_rRep);
2185 const char * lang( librdf_node_get_literal_value_language(i_pNode) );
2186 librdf_uri* pType(
2187 librdf_node_get_literal_value_datatype_uri(i_pNode) );
2188 OSL_ENSURE(!lang || !pType, "convertToXNode: invalid literal");
2189 const ::rtl::OUString valueU( ::rtl::OStringToOUString(
2190 ::rtl::OString(reinterpret_cast<const sal_Char*>(value)),
2191 RTL_TEXTENCODING_UTF8) );
2192 if (lang) {
2193 const ::rtl::OUString langU( ::rtl::OStringToOUString(
2194 ::rtl::OString(reinterpret_cast<const sal_Char*>(lang)),
2195 RTL_TEXTENCODING_UTF8) );
2196 return uno::Reference<rdf::XNode>(
2197 rdf::Literal::createWithLanguage(m_xContext, valueU, langU),
2198 uno::UNO_QUERY);
2199 } else if (pType) {
2200 uno::Reference<rdf::XURI> xType(convertToXURI(pType));
2201 OSL_ENSURE(xType.is(), "convertToXNode: null uri");
2202 return uno::Reference<rdf::XNode>(
2203 rdf::Literal::createWithType(m_xContext, valueU, xType),
2204 uno::UNO_QUERY);
2205 } else {
2206 return uno::Reference<rdf::XNode>(
2207 rdf::Literal::create(m_xContext, valueU),
2208 uno::UNO_QUERY);
2212 rdf::Statement
2213 librdf_TypeConverter::convertToStatement(librdf_statement* i_pStmt,
2214 librdf_node* i_pContext) const
2216 if (!i_pStmt) {
2217 throw uno::RuntimeException();
2219 return rdf::Statement(
2220 convertToXResource(librdf_statement_get_subject(i_pStmt)),
2221 convertToXURI(librdf_statement_get_predicate(i_pStmt)),
2222 convertToXNode(librdf_statement_get_object(i_pStmt)),
2223 convertToXURI(i_pContext));
2226 } // closing anonymous implementation namespace
2230 // component helper namespace
2231 namespace comp_librdf_Repository {
2233 ::rtl::OUString SAL_CALL _getImplementationName() {
2234 return rtl::OUString("librdf_Repository");
2237 uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
2239 uno::Sequence< ::rtl::OUString > s(1);
2240 s[0] = "com.sun.star.rdf.Repository";
2241 return s;
2244 uno::Reference< uno::XInterface > SAL_CALL _create(
2245 const uno::Reference< uno::XComponentContext > & context)
2246 SAL_THROW((uno::Exception))
2248 return static_cast< ::cppu::OWeakObject * >(new librdf_Repository(context));
2251 } // closing component helper namespace
2253 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */