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