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