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