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