1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3 * Copyright (c) 2010 GPL. V2+ copyright to AbiSource B.V.
4 * This file was originally written by Ben Martin in 2010.
5 * Updates by Ben Martin in 2011.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23
24 #include "pd_DocumentRDF.h"
25 #include "pd_Document.h"
26 #include "pt_PieceTable.h"
27 #include "ut_debugmsg.h"
28 #include "pf_Frag_Object.h"
29 #include "pf_Frag_Strux.h"
30 #include "ut_std_string.h"
31 #include "ut_conversion.h"
32 #include "xap_App.h"
33
34 #include <sstream>
35 #include <set>
36 #include <fstream>
37
38 #include <iterator>
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 #include "pd_RDFQuery.h"
44
45
46 #define DEBUG_LOWLEVEL_IO 0
47
48 typedef std::map< std::string, std::string > stringmap_t;
49
50 /******************************/
51 /******************************/
52 /******************************/
53
54 class PD_SemanticItemFactoryNull
55 :
56 public PD_SemanticItemFactory
57 {
58 public:
createContact(PD_DocumentRDFHandle,PD_ResultBindings_t::iterator)59 virtual PD_RDFContact* createContact(PD_DocumentRDFHandle /*rdf*/,
60 PD_ResultBindings_t::iterator /*it*/)
61 {
62 return 0;
63 }
createEvent(PD_DocumentRDFHandle,PD_ResultBindings_t::iterator)64 virtual PD_RDFEvent* createEvent(PD_DocumentRDFHandle /*rdf*/,
65 PD_ResultBindings_t::iterator /*it*/)
66 {
67 return 0;
68 }
createLocation(PD_DocumentRDFHandle,PD_ResultBindings_t::iterator,bool isGeo84=false)69 virtual PD_RDFLocation* createLocation(PD_DocumentRDFHandle /*rdf*/,
70 PD_ResultBindings_t::iterator /*it*/,
71 bool isGeo84 = false )
72 {
73 UT_UNUSED(isGeo84);
74 return 0;
75 }
76 };
77 PD_SemanticItemFactory *PD_DocumentRDF::s_SemanticItemFactory;
getSemanticItemFactory()78 PD_SemanticItemFactory *PD_DocumentRDF::getSemanticItemFactory()
79 {
80 if (!s_SemanticItemFactory) s_SemanticItemFactory = new PD_SemanticItemFactoryNull;
81 return s_SemanticItemFactory;
82 }
83 void
setSemanticItemFactory(PD_SemanticItemFactory * f)84 PD_DocumentRDF::setSemanticItemFactory( PD_SemanticItemFactory* f )
85 {
86 s_SemanticItemFactory = f;
87 }
88
89
90 class PD_RDFDialogsNull : public PD_RDFDialogs
91 {
92 public:
runSemanticStylesheetsDialog(FV_View *)93 virtual void runSemanticStylesheetsDialog(FV_View* /*pView*/)
94 {
95 }
runInsertReferenceDialog(FV_View *)96 virtual std::pair< PT_DocPosition, PT_DocPosition > runInsertReferenceDialog(FV_View* /*pView*/)
97 {
98 return std::make_pair(0,0);
99 }
100 };
101 PD_RDFDialogs *PD_DocumentRDF::s_RDFDialogs;
getRDFDialogs()102 PD_RDFDialogs *PD_DocumentRDF::getRDFDialogs()
103 {
104 if (!s_RDFDialogs) s_RDFDialogs = new PD_RDFDialogsNull;
105 return s_RDFDialogs;
106 }
107 void
setRDFDialogs(PD_RDFDialogs * d)108 PD_DocumentRDF::setRDFDialogs( PD_RDFDialogs* d )
109 {
110 s_RDFDialogs = d;
111 }
112
runInsertReferenceDialog(FV_View * pView)113 std::pair< PT_DocPosition, PT_DocPosition > runInsertReferenceDialog( FV_View* pView )
114 {
115 return PD_DocumentRDF::getRDFDialogs()->runInsertReferenceDialog( pView );
116 }
117
runSemanticStylesheetsDialog(FV_View * pView)118 void runSemanticStylesheetsDialog( FV_View* pView )
119 {
120 PD_DocumentRDF::getRDFDialogs()->runSemanticStylesheetsDialog( pView );
121 }
122
123
124
125 /******************************/
126 /******************************/
127 /******************************/
128
129
130
PD_RDFModel()131 PD_RDFModel::PD_RDFModel()
132 : m_version(0)
133 {
134 }
135
136
137 void
incremenetVersion()138 PD_RDFModel::incremenetVersion()
139 {
140 m_version++;
141 }
142
143
144
145 /**
146 * Grab the first URI in the list or a default constructed one for empty lists.
147 */
148 PD_URI
front(const PD_URIList & l) const149 PD_RDFModel::front( const PD_URIList& l ) const
150 {
151 if(l.empty())
152 {
153 return PD_URI();
154 }
155 return l.front();
156 }
157 PD_Object
front(const PD_ObjectList & l) const158 PD_RDFModel::front( const PD_ObjectList& l ) const
159 {
160 if(l.empty())
161 {
162 return PD_Object();
163 }
164 return l.front();
165 }
166
167
168 /**
169 * Get an object which has the given subject and predicate. If there
170 * are more than one such object, any one of those will be returned.
171 * So you should only use this method when the RDF only allows a
172 * single matching triple.
173 */
174 PD_Object
getObject(const PD_URI & s,const PD_URI & p)175 PD_RDFModel::getObject( const PD_URI& s, const PD_URI& p )
176 {
177 PD_ObjectList l = getObjects(s,p);
178 return front(l);
179 }
180
181 /**
182 * Similar to getSubjects but returns any one of the matches if there are
183 * more than one. Use this method when the RDF schema only allows a single
184 * matching triple.
185 */
186 PD_URI
getSubject(const PD_URI & p,const PD_Object & o)187 PD_RDFModel::getSubject( const PD_URI& p, const PD_Object& o )
188 {
189 PD_URIList l = getSubjects( p,o );
190 return front(l);
191 }
192
193 PD_ObjectList
getObjects(const PD_URI & s,const PD_URI & p)194 PD_RDFModel::getObjects( const PD_URI& s, const PD_URI& p )
195 {
196 PD_ObjectList ret;
197 PD_RDFModelIterator iter = begin();
198 PD_RDFModelIterator e = end();
199 for( ; iter != e; ++iter )
200 {
201 const PD_RDFStatement& st = *iter;
202 if( st.getSubject() == s && st.getPredicate() == p )
203 {
204 ret.push_back( st.getObject() );
205 }
206 }
207 return ret;
208 }
209
210 PD_URIList
getSubjects(const PD_URI & p,const PD_Object & o)211 PD_RDFModel::getSubjects( const PD_URI& p, const PD_Object& o )
212 {
213 PD_URIList ret;
214 PD_RDFModelIterator iter = begin();
215 PD_RDFModelIterator e = end();
216 for( ; iter != e; ++iter )
217 {
218 const PD_RDFStatement& st = *iter;
219 if( st.getPredicate() == p && st.getObject() == o )
220 {
221 ret.push_back( st.getSubject() );
222 }
223 }
224 return ret;
225 }
226
227
228 POCol
getArcsOut(const PD_URI & s)229 PD_RDFModel::getArcsOut( const PD_URI& s )
230 {
231 POCol ret;
232 PD_RDFModelIterator iter = begin();
233 PD_RDFModelIterator e = end();
234 for( ; iter != e; ++iter )
235 {
236 const PD_RDFStatement& st = *iter;
237 if( st.getSubject() == s )
238 {
239 ret.insert( std::make_pair( st.getPredicate(), st.getObject() ));
240 }
241 }
242 return ret;
243 }
244
245
246 bool
contains(const PD_RDFStatement & st)247 PD_RDFModel::contains( const PD_RDFStatement& st )
248 {
249 return contains( st.getSubject(), st.getPredicate(), st.getObject() );
250 }
251
252 /**
253 * Test if the given triple is in the RDF or not.
254 */
255 bool
contains(const PD_URI & s,const PD_URI & p,const PD_Object & o)256 PD_RDFModel::contains( const PD_URI& s, const PD_URI& p, const PD_Object& o )
257 {
258 PD_RDFStatement sought( s, p, o );
259
260 bool ret = false;
261 PD_RDFModelIterator iter = begin();
262 PD_RDFModelIterator e = end();
263 for( ; iter != e; ++iter )
264 {
265 const PD_RDFStatement& st = *iter;
266 if( st == sought )
267 return true;
268 }
269 return ret;
270 }
271
272 long
getTripleCount()273 PD_RDFModel::getTripleCount()
274 {
275 long ret = 0;
276 PD_RDFModelIterator iter = begin();
277 PD_RDFModelIterator e = end();
278 for( ; iter != e; ++iter )
279 {
280 ++ret;
281 }
282 return ret;
283 }
284
285
286
287 /**
288 * Get a list of every subject in the model.
289 * If you want to get all triples, then first get all subjects
290 * and then use getArcsOut() to get the predicate-object combinations
291 * for each of the subjects.
292 */
293 PD_URIList
getAllSubjects()294 PD_RDFModel::getAllSubjects()
295 {
296 PD_URIList ret;
297 PD_RDFModelIterator iter = begin();
298 PD_RDFModelIterator e = end();
299 for( ; iter != e; ++iter )
300 {
301 const PD_RDFStatement& st = *iter;
302 ret.push_back( st.getSubject() );
303 }
304 return ret;
305 }
306
307
308
309 /**
310 * Test if the given subject+predicate is in the RDF or not.
311 */
312 bool
contains(const PD_URI & s,const PD_URI & p)313 PD_RDFModel::contains( const PD_URI& s, const PD_URI& p )
314 {
315 PD_URI u = getObject( s, p );
316 return u.isValid();
317 }
318
319 void
dumpModel(const std::string & headerMsg)320 PD_RDFModel::dumpModel( const std::string& headerMsg )
321 {
322 UT_DEBUG_ONLY_ARG(headerMsg);
323
324 #ifdef DEBUG
325 PD_RDFModelIterator iter = begin();
326 PD_RDFModelIterator e = end();
327
328 UT_DEBUGMSG(("PD_RDFModel::dumpModel() ----------------------------------\n"));
329 UT_DEBUGMSG(("PD_RDFModel::dumpModel() %s\n", headerMsg.c_str()));
330 UT_DEBUGMSG(("PD_RDFModel::dumpModel() triple count:%ld\n", getTripleCount()));
331 UT_DEBUGMSG(("PD_RDFModel::dumpModel() ----------------------------------\n"));
332
333 for( ; iter != e; ++iter )
334 {
335 PD_RDFStatement st = *iter;
336 UT_DEBUGMSG(("PD_RDFModel::dumpModel() st:%s\n", st.toString().c_str() ));
337
338 }
339 UT_DEBUGMSG(("PD_RDFModel::dumpModel() --- done -------------------------\n"));
340 #endif
341
342 }
343
344 std::string
uriToPrefixed(const std::string & uri)345 PD_RDFModel::uriToPrefixed( const std::string& uri )
346 {
347 uriToPrefix_t& m = getUriToPrefix();
348
349 for( uriToPrefix_t::iterator iter = m.begin();
350 iter != m.end(); ++iter )
351 {
352 const std::string& p = iter->second;
353 const std::string& ns = iter->first;
354
355 if( starts_with( uri, p ))
356 {
357 return ns + ":" + uri.substr(p.length());
358 }
359 }
360 return uri;
361 }
362
363 std::string
prefixedToURI(const std::string & prefixedstr)364 PD_RDFModel::prefixedToURI( const std::string& prefixedstr )
365 {
366 std::string::size_type colonLocation = prefixedstr.find(":");
367 if( colonLocation != std::string::npos )
368 {
369 std::string prefix = prefixedstr.substr( 0, colonLocation );
370 std::string rest = prefixedstr.substr( colonLocation+1 );
371 uriToPrefix_t& m = getUriToPrefix();
372 uriToPrefix_t::iterator mi = m.find( prefix );
373 if( mi != m.end() )
374 {
375 std::stringstream ss;
376 ss << mi->second << rest;
377 return ss.str();
378 }
379 }
380 return prefixedstr;
381 }
382
383 PD_RDFModel::uriToPrefix_t&
getUriToPrefix()384 PD_RDFModel::getUriToPrefix()
385 {
386 static uriToPrefix_t m;
387 if( m.empty() )
388 {
389 m.insert( std::make_pair( "pkg", "http://docs.oasis-open.org/opendocument/meta/package/common#" ));
390 m.insert( std::make_pair( "odf", "http://docs.oasis-open.org/opendocument/meta/package/odf#" ));
391 m.insert( std::make_pair( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ));
392 m.insert( std::make_pair( "dcterms", "http://dublincore.org/documents/dcmi-terms/#" ));
393 m.insert( std::make_pair( "cite", "http://docs.oasis-open.org/prototype/opendocument/citation#" ));
394 m.insert( std::make_pair( "foaf", "http://xmlns.com/foaf/0.1/" ));
395 m.insert( std::make_pair( "example", "http://www.example.org/xmlns/ex#" ));
396 m.insert( std::make_pair( "geo84", "http://www.w3.org/2003/01/geo/wgs84_pos#" ));
397 m.insert( std::make_pair( "rdfs", "http://www.w3.org/2000/01/rdf-schema#" ));
398 m.insert( std::make_pair( "dc", "http://purl.org/dc/elements/1.1/" ));
399 m.insert( std::make_pair( "cal", "http://www.w3.org/2002/12/cal/icaltzd#" ));
400
401 m.insert( std::make_pair( "abifoaf", "http://abicollab.net/rdf/foaf#" ));
402 }
403
404 return m;
405 }
406
407
408
409 /**
410 * Read a string which is prefixed with it's length in ascii from the
411 * given stream.
412 * @param iss stream to read length and string from
413 * @return string
414 */
readLengthPrefixedString(std::istream & iss)415 static std::string readLengthPrefixedString( std::istream& iss )
416 {
417 char ch;
418 int len = 0;
419 iss >> len >> std::noskipws >> ch;
420
421 #if DEBUG
422 if( DEBUG_LOWLEVEL_IO )
423 {
424 off_t loc = iss.tellg();
425 UT_DEBUGMSG(("PD_DocumentRDF::readLengthPrefixedString() len:%d loc:%ld\n",
426 len, (long)loc));
427 }
428 #endif
429
430 char* p = new char[len+2];
431 memset( p, 0, len+2 );
432 iss.read( p, len );
433 std::string ret = p;
434 delete [] p;
435 return ret;
436 }
437
438 /**
439 * Given a string z, create a new string which contains the length of z
440 * as an ascii string, a space and then z itself.
441 * @param s the string z to create a length z string from
442 * @return a string containing the length of z, a space, then z
443 */
createLengthPrefixedString(const std::string & s)444 static std::string createLengthPrefixedString( const std::string& s )
445 {
446 std::stringstream ss;
447 ss << s.length() << " " << s;
448 return ss.str();
449 }
450
451 /**
452 * Given an predicate and object, create a serialized "packed" double of these two.
453 * @see splitPO()
454 */
combinePO(const PD_URI & p,const PD_Object & o)455 static std::string combinePO(const PD_URI& p, const PD_Object& o )
456 {
457 std::stringstream ss;
458 p.write(ss);
459 o.write(ss);
460 return ss.str();
461 }
462
463
464 /**
465 * Split up a packed double that contains a predicate and object.
466 * @see combinePO()
467 */
splitPO(const std::string & po)468 static std::pair< PD_URI, PD_Object > splitPO( const std::string& po )
469 {
470 std::stringstream ss;
471 ss << po;
472
473 PD_URI p;
474 PD_Object o;
475 p.read( ss );
476 o.read( ss );
477 return std::make_pair( p, o );
478 }
479
480 /**
481 * Decode a list of predicate,object pairings that was created with encodePOCol().
482 *
483 * @see encodePOCol()
484 */
decodePOCol(const std::string & data)485 static POCol decodePOCol( const std::string& data )
486 {
487 // UT_DEBUGMSG(("PD_DocumentRDF::decodePOCol() data:%s\n", data.c_str() ));
488 POCol ret;
489 if( data.empty() )
490 return ret;
491
492 char ch;
493 int sz = 0;
494 std::stringstream ss;
495 ss << data;
496 ss >> sz >> std::noskipws >> ch;
497 // UT_DEBUGMSG(("PD_DocumentRDF::decodePOCol() sz:%d\n", sz ));
498 for( int i=0; i<sz; ++i )
499 {
500 std::string po = readLengthPrefixedString( ss );
501 ss >> std::noskipws >> ch;
502 // UT_DEBUGMSG(("PD_DocumentRDF::decodePOCol() po:%s\n", po.c_str() ));
503
504 std::pair< PD_URI, PD_Object > p = splitPO( po );
505 ret.insert(p);
506 }
507 return ret;
508 }
509
510
511 /**
512 * Encode a list of predicate,object pairings into a single string.
513 *
514 * @see decodePOCol()
515 */
encodePOCol(const POCol & l)516 static std::string encodePOCol( const POCol& l )
517 {
518 std::stringstream ss;
519 ss << l.size() << " ";
520 POCol::const_iterator e = l.end();
521 for( POCol::const_iterator iter = l.begin(); iter != e; ++iter )
522 {
523 std::string po = combinePO( iter->first, iter->second );
524 ss << createLengthPrefixedString(po) << ' ';
525 }
526 return ss.str();
527 }
528
529 /********************************************************************************/
530 /********************************************************************************/
531 /********************************************************************************/
532 /********************************************************************************/
533
PD_URI(const std::string & v)534 PD_URI::PD_URI( const std::string& v )
535 :
536 m_value( v )
537 {
538 }
539
540 /**
541 * get a std::string representation
542 */
toString() const543 std::string PD_URI::toString() const
544 {
545 return m_value;
546 }
547
length() const548 int PD_URI::length() const
549 {
550 return m_value.length();
551 }
552
553 /**
554 * Only very basic tests for validity are performed. The
555 * main use of this method is to detect default constructed
556 * PD_URI values
557 */
isValid() const558 bool PD_URI::isValid() const
559 {
560 return !m_value.empty();
561 }
562
operator ==(const PD_URI & b) const563 bool PD_URI::operator==(const PD_URI& b) const
564 {
565 return m_value == b.m_value;
566 }
567
operator ==(const std::string & b) const568 bool PD_URI::operator==(const std::string& b) const
569 {
570 return m_value == b;
571 }
572
operator <(const PD_URI & b) const573 bool PD_URI::operator<(const PD_URI& b) const
574 {
575 return m_value < b.m_value;
576 }
577
578 PD_URI
prefixedToURI(PD_RDFModelHandle model) const579 PD_URI::prefixedToURI( PD_RDFModelHandle model ) const
580 {
581 PD_URI ret( model->prefixedToURI( toString() ));
582 return ret;
583 }
584
585 /**
586 * Deserialize the PD_URI from the given stream.
587 *
588 * I thought about using boost::serialization for this, as it
589 * is doing a similar thing. Using b::s though would have required
590 * a link dependancy.
591 *
592 * @see write()
593 */
read(std::istream & ss)594 bool PD_URI::read( std::istream& ss )
595 {
596 char ch;
597 int version = 0;
598 int numParts = 0;
599 ss >> version >> std::noskipws >> ch;
600 ss >> numParts >> std::noskipws >> ch;
601 m_value = readLengthPrefixedString(ss);
602 ss >> std::noskipws >> ch;
603 return true;
604 }
605
606 /**
607 * Write the URI to the given stream.
608 * @see read()
609 */
write(std::ostream & ss) const610 bool PD_URI::write( std::ostream& ss ) const
611 {
612 int version = 1;
613 int numParts = 1;
614 ss << version << " " << numParts << " ";
615 ss << createLengthPrefixedString(m_value) << " ";
616 return true;
617 }
618
operator <(std::pair<PD_URI,PD_URI> a,PD_URI b)619 bool operator<( std::pair< PD_URI, PD_URI > a, PD_URI b)
620 {
621 return a.first.toString() < b.toString();
622 }
623
operator <(PD_URI a,std::pair<PD_URI,PD_URI> b)624 bool operator<( PD_URI a, std::pair< PD_URI, PD_URI > b )
625 {
626 return a.toString() < b.first.toString();
627 }
628
629 /****************************************/
630 /****************************************/
631 /****************************************/
632
PD_Object(const std::string & v)633 PD_Object::PD_Object( const std::string& v )
634 : PD_URI(v)
635 , m_objectType( OBJECT_TYPE_URI )
636 {
637 }
638
PD_Object(const PD_URI & u)639 PD_Object::PD_Object( const PD_URI& u )
640 : PD_URI(u.toString())
641 , m_objectType( OBJECT_TYPE_URI )
642 {
643 }
644
645
646
PD_Object(const std::string & v,int objectType,const std::string & type)647 PD_Object::PD_Object( const std::string& v, int objectType, const std::string& type )
648 : PD_URI(v)
649 , m_xsdType(type)
650 , m_objectType(objectType)
651 {
652 }
653
getObjectType() const654 int PD_Object::getObjectType() const
655 {
656 return m_objectType;
657 }
658
isLiteral() const659 bool PD_Object::isLiteral() const
660 {
661 return m_objectType == OBJECT_TYPE_LITERAL;
662 }
663
isURI() const664 bool PD_Object::isURI() const
665 {
666 return m_objectType == OBJECT_TYPE_URI;
667 }
668
isBNode() const669 bool PD_Object::isBNode() const
670 {
671 return m_objectType == OBJECT_TYPE_BNODE;
672 }
673
674
675
676
getXSDType() const677 std::string PD_Object::getXSDType() const
678 {
679 return m_xsdType;
680 }
681
hasXSDType() const682 bool PD_Object::hasXSDType() const
683 {
684 return !m_xsdType.empty();
685 }
686
687
read(std::istream & ss)688 bool PD_Object::read( std::istream& ss )
689 {
690 char ch;
691 int version = 0;
692 int numParts = 0;
693 ss >> version >> std::noskipws >> ch;
694 ss >> numParts >> std::noskipws >> ch;
695 ss >> m_objectType >> std::noskipws >> ch;
696 m_value = readLengthPrefixedString(ss);
697 ss >> std::noskipws >> ch;
698 m_xsdType = readLengthPrefixedString(ss);
699 ss >> std::noskipws >> ch;
700 m_context = readLengthPrefixedString(ss);
701 ss >> std::noskipws >> ch;
702 return true;
703 }
704
write(std::ostream & ss) const705 bool PD_Object::write( std::ostream& ss ) const
706 {
707 int version = 1;
708 int numParts = 4;
709 ss << version << " " << numParts << " ";
710 ss << m_objectType << " ";
711 ss << createLengthPrefixedString(m_value) << " ";
712 ss << createLengthPrefixedString(m_xsdType) << " ";
713 ss << createLengthPrefixedString(m_context) << " ";
714 return true;
715 }
716
PD_Literal(const std::string & v,const std::string & xsdtype)717 PD_Literal::PD_Literal( const std::string& v, const std::string& xsdtype )
718 :
719 PD_Object( v, OBJECT_TYPE_LITERAL, xsdtype )
720 {
721 }
722
723 /****************************************/
724 /****************************************/
725 /****************************************/
726
PD_RDFStatement()727 PD_RDFStatement::PD_RDFStatement()
728 : m_isValid( false )
729 {
730 }
731
732 PD_RDFStatement
prefixedToURI(PD_RDFModelHandle model) const733 PD_RDFStatement::prefixedToURI( PD_RDFModelHandle model ) const
734 {
735 PD_RDFStatement ret( model->prefixedToURI( getSubject().toString()),
736 model->prefixedToURI( getPredicate().toString()),
737 PD_Object( model->prefixedToURI( getObject().toString())));
738 return ret;
739 }
740
741
742 PD_RDFStatement
uriToPrefixed(PD_RDFModelHandle model) const743 PD_RDFStatement::uriToPrefixed( PD_RDFModelHandle model ) const
744 {
745 PD_RDFStatement ret( model->uriToPrefixed( getSubject().toString()),
746 model->uriToPrefixed( getPredicate().toString()),
747 PD_Object( model->uriToPrefixed( getObject().toString())));
748 return ret;
749 }
750
751 bool
operator ==(const PD_RDFStatement & b) const752 PD_RDFStatement::operator==(const PD_RDFStatement& b) const
753 {
754 return getSubject() == b.getSubject()
755 && getPredicate() == b.getPredicate()
756 && getObject() == b.getObject();
757 }
758
759
760
PD_RDFStatement(PD_RDFModelHandle model,const PD_URI & s,const PD_URI & p,const PD_Object & o)761 PD_RDFStatement::PD_RDFStatement( PD_RDFModelHandle model, const PD_URI& s, const PD_URI& p, const PD_Object& o )
762 : m_subject( s.prefixedToURI(model) )
763 , m_predicate( p.prefixedToURI(model) )
764 , m_object( o.prefixedToURI(model).toString() )
765 , m_isValid( true )
766 {
767 }
768
769
PD_RDFStatement(const PD_URI & s,const PD_URI & p,const PD_Object & o)770 PD_RDFStatement::PD_RDFStatement( const PD_URI& s, const PD_URI& p, const PD_Object& o )
771 : m_subject( s )
772 , m_predicate( p )
773 , m_object( o )
774 , m_isValid( true )
775 {
776 }
777
PD_RDFStatement(const std::string & s,const std::string & p,const PD_Object & o)778 PD_RDFStatement::PD_RDFStatement( const std::string& s, const std::string& p, const PD_Object& o )
779 : m_subject( PD_URI(s) )
780 , m_predicate( PD_URI(p) )
781 , m_object( o )
782 , m_isValid( true )
783 {
784 }
785
PD_RDFStatement(const std::string & s,const std::string & p,const PD_Literal & o)786 PD_RDFStatement::PD_RDFStatement( const std::string& s, const std::string& p, const PD_Literal& o )
787 : m_subject( PD_URI(s) )
788 , m_predicate( PD_URI(p) )
789 , m_object( o )
790 , m_isValid( true )
791 {
792 }
793
794
795
796
797 const PD_URI&
getSubject() const798 PD_RDFStatement::getSubject() const
799 {
800 return m_subject;
801 }
802
803 const PD_URI&
getPredicate() const804 PD_RDFStatement::getPredicate() const
805 {
806 return m_predicate;
807 }
808
809 const PD_Object&
getObject() const810 PD_RDFStatement::getObject() const
811 {
812 return m_object;
813 }
814
815 bool
isValid() const816 PD_RDFStatement::isValid() const
817 {
818 return m_isValid;
819 }
820
821 std::string
toString() const822 PD_RDFStatement::toString() const
823 {
824 std::stringstream ss;
825 ss << " s:" << m_subject.toString()
826 << " p:" << m_predicate.toString()
827 << " ot:" << m_object.getObjectType() << " o:" << m_object.toString() << " ";
828 return ss.str();
829 }
830
831
832
833
834 /****************************************/
835 /****************************************/
836 /****************************************/
837 /****************************************/
838 /****************************************/
839 /****************************************/
840
841 class PD_RDFModelFromAP : public PD_DocumentRDF
842 {
843 // Can't do this...
844 PD_RDFModelFromAP& operator=( const PD_RDFModelFromAP& other );
845
846 protected:
847
848 const PP_AttrProp* m_AP;
849
850 public:
851
PD_RDFModelFromAP(PD_Document * doc,const PP_AttrProp * AP)852 explicit PD_RDFModelFromAP( PD_Document* doc, const PP_AttrProp* AP )
853 :
854 PD_DocumentRDF( doc ),
855 m_AP(AP)
856 {
857 UT_DEBUGMSG((" PD_RDFModelFromAP() this:%p\n",this));
858 }
~PD_RDFModelFromAP()859 virtual ~PD_RDFModelFromAP()
860 {
861 UT_DEBUGMSG(("~PD_RDFModelFromAP() this:%p\n",this));
862 delete m_AP;
863 }
getAP(void)864 virtual const PP_AttrProp* getAP(void)
865 {
866 return m_AP;
867 }
setAP(PP_AttrProp * newAP)868 virtual UT_Error setAP( PP_AttrProp* newAP )
869 {
870 delete m_AP;
871 m_AP = newAP;
872 return UT_OK;
873 }
isStandAlone() const874 virtual bool isStandAlone() const
875 {
876 return true;
877 }
maybeSetDocumentDirty()878 virtual void maybeSetDocumentDirty()
879 {
880 }
881
882 };
883
884
885 /**
886 * The idea of this class is to be able to slice up a document's RDF.
887 * So you can explicitly say, give me the RDF that is contained in all
888 * the AP between two positions in the document.
889 */
890 class PD_RDFModelFromStartEndPos : public PD_DocumentRDF
891 {
892 PT_DocPosition m_beginPos;
893 PT_DocPosition m_endPos;
894
895 public:
PD_RDFModelFromStartEndPos(PD_Document * doc,PT_DocPosition b,PT_DocPosition e)896 explicit PD_RDFModelFromStartEndPos( PD_Document* doc, PT_DocPosition b, PT_DocPosition e )
897 : PD_DocumentRDF(doc)
898 , m_beginPos(b)
899 , m_endPos(e)
900 {
901 updateAPList();
902 }
~PD_RDFModelFromStartEndPos()903 virtual ~PD_RDFModelFromStartEndPos()
904 {
905 }
getAP(void)906 virtual const PP_AttrProp* getAP(void)
907 {
908 UT_DEBUGMSG(("ERROR: getAP() is not valid for a start-end position rdf model\n"));
909 return 0;
910 }
setAP(PP_AttrProp * newAP)911 virtual UT_Error setAP( PP_AttrProp* newAP )
912 {
913 UT_UNUSED( newAP );
914 return UT_OK;
915 }
isStandAlone() const916 virtual bool isStandAlone() const
917 {
918 return true;
919 }
920
921 ////////////////
922 // For iterating over the PP_AttrProp that are in range.
923 typedef std::list< const PP_AttrProp* > m_APList_t;
924 m_APList_t m_APList;
updateAPList()925 void updateAPList()
926 {
927 m_APList.clear();
928
929 pf_Frag* frag = m_doc->getFragFromPosition( m_beginPos );
930 pf_Frag* endFrag = m_doc->getFragFromPosition( m_endPos );
931 if( !frag || !endFrag )
932 {
933 UT_DEBUGMSG(("updateAPList() bpos:%d epos:%d frag:%p endFrag:%p\n",
934 m_beginPos, m_endPos, frag, endFrag ));
935 return;
936 }
937
938 endFrag = endFrag->getNext();
939
940 for( ; frag != endFrag; frag = frag->getNext() )
941 {
942 PT_AttrPropIndex api = frag->getIndexAP();
943 const PP_AttrProp * pAP = 0;
944 m_doc->getAttrProp( api, &pAP );
945 m_APList.push_back( pAP );
946 }
947 }
apBegin()948 m_APList_t::iterator apBegin()
949 {
950 return m_APList.begin();
951 }
952
apEnd()953 m_APList_t::iterator apEnd()
954 {
955 return m_APList.end();
956 }
957
958 ////////////////
959 // Statement iterator methods...
960 // PD_RDFStatement
961 class StatementIterator
962 :
963 public std::iterator< std::forward_iterator_tag, PD_RDFStatement >
964 {
965 private:
966 typedef std::list< const PP_AttrProp* > m_APList_t;
967 bool m_end;
968 m_APList_t::iterator m_apiter;
969 m_APList_t::iterator m_apenditer;
970 size_t m_apPropertyNumber;
971 std::string m_subject;
972 POCol m_pocol;
973 POCol::iterator m_pocoliter;
974 PD_RDFStatement m_current;
975
976 public:
977 typedef StatementIterator& self_reference;
978 typedef StatementIterator self_type;
979
StatementIterator()980 StatementIterator()
981 : m_end( true )
982 , m_apPropertyNumber( 0 )
983 {
984 }
StatementIterator(m_APList_t::iterator iter,m_APList_t::iterator enditer)985 StatementIterator( m_APList_t::iterator iter, m_APList_t::iterator enditer )
986 : m_end( false )
987 , m_apiter( iter )
988 , m_apenditer( enditer )
989 , m_apPropertyNumber( 0 )
990 {
991 }
992
advance_apiter()993 void advance_apiter()
994 {
995 ++m_apiter;
996 if( m_apiter == m_apenditer )
997 {
998 m_end = true;
999 return;
1000 }
1001 m_apPropertyNumber = 0;
1002 m_subject = "";
1003 m_pocol.clear();
1004 m_pocoliter = m_pocol.end();
1005 }
setup_pocol()1006 void setup_pocol()
1007 {
1008 UT_DEBUGMSG(("SI... statement iter++/setup_pocol(top)\n" ));
1009 const gchar * szName = 0;
1010 const gchar * szValue = 0;
1011 const PP_AttrProp* AP = *m_apiter;
1012 if( AP->getNthProperty( m_apPropertyNumber, szName, szValue) )
1013 {
1014 // UT_DEBUGMSG(("statement iter++/setup_pocol szName :%s\n", szName ));
1015 // UT_DEBUGMSG(("statement iter++/setup_pocol szValue:%s\n", szValue ));
1016 m_subject = szName;
1017 m_pocol = decodePOCol( szValue );
1018 if( m_pocol.empty() )
1019 return;
1020
1021 m_pocoliter = m_pocol.begin();
1022
1023 std::string pred = m_pocoliter->first.toString();
1024 PD_Object obj = m_pocoliter->second;
1025 m_current = PD_RDFStatement( m_subject, pred, obj );
1026 }
1027 }
1028
operator ++()1029 self_reference operator++()
1030 {
1031 if( m_end )
1032 return *this;
1033 if( m_apiter == m_apenditer )
1034 {
1035 m_end = true;
1036 return *this;
1037 }
1038
1039 /**
1040 * We have to walk over each AP using m_apiter until we hit m_apenditer
1041 *
1042 * For each of these AP;
1043 * we have to walk over all the properties
1044 * ( each prop is a subject -> list[ pred+obj ] )
1045 *
1046 * For each of these properties;
1047 * we have to walk over all the pairs in the pocol.
1048 */
1049
1050 /// FIXME:
1051
1052
1053 const PP_AttrProp* AP = *m_apiter;
1054 size_t count = AP->getPropertyCount();
1055 // if( m_apPropertyNumber == count )
1056 // {
1057 // advance_apiter();
1058 // return operator++();
1059 // }
1060 while( m_pocol.empty() )
1061 {
1062 if( m_apPropertyNumber == count )
1063 {
1064 advance_apiter();
1065 return operator++();
1066 }
1067 setup_pocol();
1068 ++m_apPropertyNumber;
1069 }
1070
1071 std::string pred = m_pocoliter->first.toString();
1072 PD_Object obj = m_pocoliter->second;
1073 m_current = PD_RDFStatement( m_subject, pred, obj );
1074 ++m_pocoliter;
1075 if( m_pocoliter == m_pocol.end() )
1076 {
1077 m_pocol.clear();
1078 }
1079
1080 return *this;
1081 }
operator ++(int)1082 self_type operator++(int)
1083 {
1084 self_type result( *this );
1085 ++( *this );
1086 return result;
1087 }
1088
operator ==(const self_reference other)1089 bool operator==( const self_reference other )
1090 {
1091 if( m_end && other.m_end )
1092 return true;
1093 if( (!m_end && other.m_end)
1094 || (m_end && !other.m_end) )
1095 {
1096 return false;
1097 }
1098 return m_apPropertyNumber == other.m_apPropertyNumber
1099 && m_pocoliter == other.m_pocoliter
1100 && m_apiter == other.m_apiter;
1101 }
operator !=(const self_reference other)1102 bool operator!=( const self_reference other )
1103 {
1104 return !operator==(other);
1105 }
operator *()1106 reference operator*()
1107 {
1108 return m_current;
1109 }
1110 };
1111
1112 // StatementIterator begin()
1113 // {
1114 // return StatementIterator( apBegin(), apEnd() );
1115 // }
1116 // StatementIterator end()
1117 // {
1118 // return StatementIterator();
1119 // }
1120
1121
1122
1123
1124 ////////////////
1125 // PD_RDFModel methods...
1126
getObjects(const PD_URI & s,const PD_URI & p)1127 virtual PD_ObjectList getObjects( const PD_URI& s, const PD_URI& p )
1128 {
1129 PD_ObjectList ret;
1130 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1131 apGetObjects( *iter, ret, s, p );
1132 return ret;
1133 }
1134
getObject(const PD_URI & s,const PD_URI & p)1135 virtual PD_Object getObject( const PD_URI& s, const PD_URI& p )
1136 {
1137 PD_ObjectList l = getObjects(s,p);
1138 return front(l);
1139 }
1140
getSubjects(const PD_URI & p,const PD_Object & o)1141 virtual PD_URIList getSubjects( const PD_URI& p, const PD_Object& o )
1142 {
1143 PD_URIList ret;
1144 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1145 apGetSubjects( *iter, ret, p, o );
1146 return ret;
1147 }
1148
getSubject(const PD_URI & p,const PD_Object & o)1149 virtual PD_URI getSubject( const PD_URI& p, const PD_Object& o )
1150 {
1151 PD_URIList l = getSubjects( p,o );
1152 return front(l);
1153 }
1154
getAllSubjects()1155 virtual PD_URIList getAllSubjects()
1156 {
1157 PD_URIList ret;
1158 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1159 apGetAllSubjects( *iter, ret );
1160 return ret;
1161 }
1162
getArcsOut(const PD_URI & s)1163 virtual POCol getArcsOut( const PD_URI& s )
1164 {
1165 POCol ret;
1166 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1167 apGetArcsOut( *iter, ret, s );
1168 return ret;
1169 }
1170
contains(const PD_URI & s,const PD_URI & p,const PD_Object & o)1171 virtual bool contains( const PD_URI& s, const PD_URI& p, const PD_Object& o )
1172 {
1173 bool ret = false;
1174 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1175 {
1176 ret |= apContains( *iter, s, p, o );
1177 if( ret )
1178 break;
1179 }
1180 return ret;
1181 }
1182
dumpModel(const std::string & headerMsg="dumpModel()")1183 virtual void dumpModel( const std::string& headerMsg = "dumpModel()" )
1184 {
1185 UT_DEBUG_ONLY_ARG(headerMsg);
1186
1187 #ifdef DEBUG
1188 UT_DEBUGMSG(("PD_RDFModelFromStartEndPos::dumpModel() doc:%p\n", m_doc));
1189 for( m_APList_t::iterator iter = apBegin(); iter != apEnd(); ++iter )
1190 apDumpModel( *iter, headerMsg );
1191 #endif
1192 }
1193
1194
1195
1196
1197 };
1198
1199
1200
1201 /****************************************/
1202 /****************************************/
1203 /****************************************/
1204
PD_RDFModelIterator()1205 PD_RDFModelIterator::PD_RDFModelIterator()
1206 : m_AP( 0 )
1207 , m_end( true )
1208 , m_apPropertyNumber( 0 )
1209 {
1210 }
1211
~PD_RDFModelIterator()1212 PD_RDFModelIterator::~PD_RDFModelIterator()
1213 {
1214 xxx_UT_DEBUGMSG(("~PD_RDFModelIterator() model: %p\n", m_model.get()));
1215 }
1216
PD_RDFModelIterator(PD_RDFModelHandle model,const PP_AttrProp * AP)1217 PD_RDFModelIterator::PD_RDFModelIterator( PD_RDFModelHandle model, const PP_AttrProp* AP )
1218 : m_model( model )
1219 , m_AP( AP )
1220 , m_end( false )
1221 , m_apPropertyNumber( 0 )
1222 {
1223 xxx_UT_DEBUGMSG(("PD_RDFModelIterator() model: %p\n", model.get()));
1224 operator++();
1225 }
1226
1227 void
setup_pocol()1228 PD_RDFModelIterator::setup_pocol()
1229 {
1230 xxx_UT_DEBUGMSG(("MI statement iter++/setup_pocol(top) apn:%d\n", m_apPropertyNumber ));
1231 const gchar * szName = 0;
1232 const gchar * szValue = 0;
1233 if( m_AP->getNthProperty( m_apPropertyNumber, szName, szValue) )
1234 {
1235 xxx_UT_DEBUGMSG(("MI statement iter++/setup_pocol szName :%s\n", szName ));
1236 xxx_UT_DEBUGMSG(("MI statement iter++/setup_pocol szValue:%s\n", szValue ));
1237 m_subject = szName;
1238 m_pocol = decodePOCol( szValue );
1239 if( m_pocol.empty() )
1240 return;
1241
1242 m_pocoliter = m_pocol.begin();
1243
1244 std::string pred = m_pocoliter->first.toString();
1245 PD_Object obj = m_pocoliter->second;
1246 m_current = PD_RDFStatement( m_subject, pred, obj );
1247 }
1248 }
1249
1250 bool
moveToNextSubjectHavePOCol()1251 PD_RDFModelIterator::moveToNextSubjectHavePOCol()
1252 {
1253 return !m_pocol.empty();
1254 }
1255
1256 void
moveToNextSubjectReadPO()1257 PD_RDFModelIterator::moveToNextSubjectReadPO()
1258 {
1259 setup_pocol();
1260 std::string pred = m_pocoliter->first.toString();
1261 PD_Object obj = m_pocoliter->second;
1262 m_current = PD_RDFStatement( m_subject, pred, obj );
1263 ++m_pocoliter;
1264 if( m_pocoliter == m_pocol.end() )
1265 {
1266 m_pocol.clear();
1267 }
1268 }
1269
1270
1271 PD_RDFModelIterator::self_reference
moveToNextSubject()1272 PD_RDFModelIterator::moveToNextSubject()
1273 {
1274 if( m_end )
1275 return *this;
1276 ++m_apPropertyNumber;
1277 if( m_apPropertyNumber == m_AP->getPropertyCount() )
1278 {
1279 m_end = true;
1280 return *this;
1281 }
1282 const gchar * szName = 0;
1283 const gchar * szValue = 0;
1284 m_AP->getNthProperty( m_apPropertyNumber, szName, szValue );
1285 m_subject = szName;
1286 m_current = PD_RDFStatement( m_subject, PD_URI(), PD_Object() );
1287 m_pocol.clear();
1288 return *this;
1289 }
1290
1291
1292 PD_RDFModelIterator::self_reference
operator ++()1293 PD_RDFModelIterator::operator++()
1294 {
1295 if( m_end )
1296 return *this;
1297
1298 /**
1299 * We have to walk over each AP using m_apiter until we hit m_apenditer
1300 *
1301 * For each of these AP;
1302 * we have to walk over all the properties
1303 * ( each prop is a subject -> list[ pred+obj ] )
1304 *
1305 * For each of these properties;
1306 * we have to walk over all the pairs in the pocol.
1307 */
1308
1309 /// FIXME:
1310
1311
1312 size_t count = m_AP->getPropertyCount();
1313 while( m_pocol.empty() )
1314 {
1315 if( m_apPropertyNumber == count )
1316 {
1317 m_end = true;
1318 return *this;
1319 }
1320 setup_pocol();
1321 ++m_apPropertyNumber;
1322 }
1323
1324 std::string pred = m_pocoliter->first.toString();
1325 PD_Object obj = m_pocoliter->second;
1326 m_current = PD_RDFStatement( m_subject, pred, obj );
1327 ++m_pocoliter;
1328 if( m_pocoliter == m_pocol.end() )
1329 {
1330 m_pocol.clear();
1331 }
1332
1333 return *this;
1334 }
1335
1336 bool
operator ==(self_constref other)1337 PD_RDFModelIterator::operator==( self_constref other )
1338 {
1339 if( m_end && other.m_end )
1340 return true;
1341 if( (!m_end && other.m_end)
1342 || (m_end && !other.m_end) )
1343 {
1344 return false;
1345 }
1346 return m_apPropertyNumber == other.m_apPropertyNumber
1347 && m_pocoliter == other.m_pocoliter;
1348 }
1349
1350 PD_RDFModelIterator&
operator =(const PD_RDFModelIterator & r)1351 PD_RDFModelIterator::operator=( const PD_RDFModelIterator& r )
1352 {
1353 if( this != &r )
1354 {
1355 xxx_UT_DEBUGMSG(("PD_RDFModelIterator op=() model: %p r.model: %p\n", m_model.get(),
1356 r.m_model.get()));
1357 m_model = r.m_model;
1358 m_AP = r.m_AP;
1359 m_end = r.m_end;
1360 m_apPropertyNumber = r.m_apPropertyNumber;
1361 m_subject = r.m_subject;
1362 m_pocol = r.m_pocol;
1363 m_current = r.m_current;
1364
1365 //
1366 // m_pocoliter is an iterator into *our* m_pocol
1367 // the default op=() will just copy the iterator into
1368 // r.pocol.
1369 //
1370 {
1371 POCol::const_iterator b = r.m_pocol.begin();
1372 POCol::const_iterator i = r.m_pocoliter;
1373 int d = std::distance( b, i );
1374 m_pocoliter = m_pocol.begin();
1375 advance( m_pocoliter, d );
1376 }
1377
1378 }
1379
1380 return *this;
1381 }
1382
1383
1384
1385 /****************************************/
1386 /****************************************/
1387 /****************************************/
1388 /****************************************/
1389 /****************************************/
1390 /****************************************/
1391
1392
1393 /********************************************************************************/
1394 /********************************************************************************/
1395 /********************************************************************************/
1396 /********************************************************************************/
1397
1398
PD_RDFSemanticItem(PD_DocumentRDFHandle rdf,PD_ResultBindings_t::iterator & it)1399 PD_RDFSemanticItem::PD_RDFSemanticItem( PD_DocumentRDFHandle rdf, PD_ResultBindings_t::iterator& it )
1400 : m_rdf(rdf)
1401 , m_context( PD_DocumentRDF::getManifestURI() )
1402 {
1403 m_name = bindingAsString( it, "name" );
1404 }
1405
~PD_RDFSemanticItem()1406 PD_RDFSemanticItem::~PD_RDFSemanticItem()
1407 {
1408 }
1409
1410 std::string
name() const1411 PD_RDFSemanticItem::name() const
1412 {
1413 return m_name;
1414 }
1415
1416 void
setName(const std::string & n)1417 PD_RDFSemanticItem::setName( const std::string& n )
1418 {
1419 m_name = n;
1420 }
1421
1422 std::string
getDisplayLabel() const1423 PD_RDFSemanticItem::getDisplayLabel() const
1424 {
1425 return "Semantic Item";
1426 }
1427
1428
1429
1430
1431 std::list< std::pair< std::string, std::string> >
getImportTypes() const1432 PD_RDFSemanticItem::getImportTypes() const
1433 {
1434 std::list< std::pair< std::string, std::string> > ret;
1435 return ret;
1436 }
1437
1438
1439
1440 std::list< std::pair< std::string, std::string> >
getExportTypes() const1441 PD_RDFSemanticItem::getExportTypes() const
1442 {
1443 std::list< std::pair< std::string, std::string> > ret;
1444 return ret;
1445 }
1446
1447 std::string
getDefaultExtension() const1448 PD_RDFSemanticItem::getDefaultExtension() const
1449 {
1450 return ".unknown";
1451 }
1452
1453
1454
1455 PD_DocumentRDFHandle
getRDF() const1456 PD_RDFSemanticItem::getRDF() const
1457 {
1458 return m_rdf;
1459 }
1460
1461 PD_DocumentRDFMutationHandle
createMutation()1462 PD_RDFSemanticItem::createMutation()
1463 {
1464 return m_rdf->createMutation();
1465 }
1466
1467 std::string
requestExportFileNameByDialog()1468 PD_RDFSemanticItem::requestExportFileNameByDialog()
1469 {
1470 std::string ret = getExportToFileName( "", getDefaultExtension(), getExportTypes() );
1471 return ret;
1472 }
1473
1474
1475
1476 PD_URI
linkingSubject() const1477 PD_RDFSemanticItem::linkingSubject() const
1478 {
1479 return m_linkingSubject;
1480 }
1481
1482
1483 PD_URI
context() const1484 PD_RDFSemanticItem::context() const
1485 {
1486 return m_context;
1487 }
1488
1489 std::set< std::string >
getXMLIDs() const1490 PD_RDFSemanticItem::getXMLIDs() const
1491 {
1492 std::set< std::string > ret;
1493
1494 PD_URI linksubj = linkingSubject();
1495 PD_ObjectList ol = m_rdf->getObjects( linksubj,
1496 PD_URI("http://docs.oasis-open.org/opendocument/meta/package/common#idref"));
1497 for( PD_ObjectList::iterator it = ol.begin(); it != ol.end(); ++it )
1498 {
1499 std::string xmlid = it->toString();
1500 ret.insert(xmlid);
1501 }
1502
1503 return ret;
1504 }
1505
1506
1507
1508 void
updateFromEditorData()1509 PD_RDFSemanticItem::updateFromEditorData()
1510 {
1511 PD_DocumentRDFMutationHandle m = m_rdf->createMutation();
1512 updateFromEditorData( m );
1513 m->commit();
1514 }
1515
1516
1517
1518
1519 #include "xap_Frame.h"
1520 #include "fv_View.h"
1521
1522 std::pair< PT_DocPosition, PT_DocPosition >
insertTextWithXMLID(const std::string & textconst,const std::string & xmlid)1523 PD_RDFSemanticItem::insertTextWithXMLID( const std::string& textconst,
1524 const std::string& xmlid )
1525 {
1526 PT_DocPosition startpos = 0, endpos = 0;
1527 XAP_Frame* lff = XAP_App::getApp()->getLastFocussedFrame();
1528 if(lff)
1529 {
1530 FV_View * pView = static_cast<FV_View*>( lff->getCurrentView() );
1531
1532 std::string text = " " + textconst + " ";
1533 startpos = pView->getPoint();
1534 m_rdf->getDocument()->insertSpan( startpos, text );
1535 endpos = pView->getPoint();
1536 startpos++;
1537 endpos--;
1538
1539 pView->selectRange( startpos, endpos );
1540 pView->cmdInsertXMLID( xmlid );
1541 }
1542
1543 return std::make_pair( startpos, endpos );
1544 }
1545
1546
1547
1548
1549 std::string
bindingAsString(PD_ResultBindings_t::iterator & it,const std::string k)1550 PD_RDFSemanticItem::bindingAsString( PD_ResultBindings_t::iterator& it, const std::string k )
1551 {
1552 return (*it)[k];
1553 }
1554
1555 std::string
optionalBindingAsString(PD_ResultBindings_t::iterator & it,const std::string k)1556 PD_RDFSemanticItem::optionalBindingAsString( PD_ResultBindings_t::iterator& it, const std::string k )
1557 {
1558 std::map< std::string, std::string >& m = *it;
1559 if( m.end() == m.find(k) || m[k] == "NULL" )
1560 return "";
1561 return m[k];
1562 }
1563
1564
1565 PD_URI&
handleSubjectDefaultArgument(PD_URI & subj)1566 PD_RDFSemanticItem::handleSubjectDefaultArgument( PD_URI& subj )
1567 {
1568 if( subj.toString().empty() )
1569 {
1570 subj = linkingSubject();
1571 }
1572 return subj;
1573 }
1574
1575
1576 void
setRDFType(PD_DocumentRDFMutationHandle m,const std::string & type,PD_URI subj)1577 PD_RDFSemanticItem::setRDFType(PD_DocumentRDFMutationHandle m, const std::string& type, PD_URI subj )
1578 {
1579 handleSubjectDefaultArgument( subj );
1580
1581 std::string t = type;
1582 updateTriple( m, t, type, PD_URI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") );
1583
1584 // PD_URI pred("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
1585 // m->add( subj, pred, PD_Object(type), context() );
1586 }
1587
1588 void
setRDFType(const std::string & type,PD_URI subj)1589 PD_RDFSemanticItem::setRDFType(const std::string& type, PD_URI subj )
1590 {
1591 PD_DocumentRDFMutationHandle m = createMutation();
1592 setRDFType( m, type, subj );
1593 m->commit();
1594 }
1595
1596 void
updateTriple(PD_DocumentRDFMutationHandle m,std::string & toModify,const std::string & newValue,const PD_URI & predString)1597 PD_RDFSemanticItem::updateTriple( PD_DocumentRDFMutationHandle m, std::string& toModify, const std::string& newValue, const PD_URI& predString )
1598 {
1599 m->remove( linkingSubject(), PD_URI( predString ) );
1600 updateTriple_remove( m, toModify, predString, linkingSubject() );
1601 toModify = newValue;
1602 updateTriple_add( m, toModify, predString, linkingSubject() );
1603 }
1604
1605 void
updateTriple(PD_DocumentRDFMutationHandle m,time_t & toModify,time_t newValue,const PD_URI & predString)1606 PD_RDFSemanticItem::updateTriple( PD_DocumentRDFMutationHandle m, time_t& toModify, time_t newValue, const PD_URI& predString )
1607 {
1608 m->remove( linkingSubject(), PD_URI( predString ) );
1609 updateTriple_remove( m, PD_URI(tostr(toModify)), predString, linkingSubject() );
1610 toModify = newValue;
1611 updateTriple_add( m, PD_URI(toTimeString(toModify)), predString, linkingSubject() );
1612 }
1613
1614 void
updateTriple(PD_DocumentRDFMutationHandle m,double & toModify,double newValue,const PD_URI & predString)1615 PD_RDFSemanticItem::updateTriple( PD_DocumentRDFMutationHandle m, double& toModify, double newValue, const PD_URI& predString )
1616 {
1617 m->remove( linkingSubject(), PD_URI( predString ) );
1618 //
1619 // I abstracted the below code to an ::remove() method in mutation
1620 // {
1621 // PD_URI pred( predString );
1622 // PD_ObjectList objects = m_rdf->getObjects( linkingSubject(), pred );
1623 // std::list< PD_RDFStatement > removeList;
1624 // for( PD_ObjectList::iterator it = objects.begin(); it != objects.end(); ++it )
1625 // {
1626 // PD_Object obj = *it;
1627 // PD_RDFStatement s( linkingSubject(), pred, obj );
1628
1629 // removeList.push_back( s );
1630 // }
1631 // m->remove( removeList );
1632 // }
1633 updateTriple_remove( m, PD_URI(tostr(toModify)), predString, linkingSubject() );
1634 toModify = newValue;
1635 updateTriple_add( m, PD_URI(tostr(toModify)), predString, linkingSubject() );
1636 }
1637
1638 void
updateTriple(PD_DocumentRDFMutationHandle m,double & toModify,double newValue,const PD_URI & predString,PD_URI linkingSubj)1639 PD_RDFSemanticItem::updateTriple( PD_DocumentRDFMutationHandle m,
1640 double& toModify, double newValue,
1641 const PD_URI& predString,
1642 PD_URI linkingSubj )
1643 {
1644 updateTriple_remove( m, PD_URI(tostr(toModify)), predString, linkingSubj );
1645 toModify = newValue;
1646 updateTriple_add( m, PD_URI(tostr(toModify)), predString, linkingSubj );
1647 }
1648
1649 void
updateTriple(std::string & toModify,const std::string & newValue,const PD_URI & predString)1650 PD_RDFSemanticItem::updateTriple( std::string& toModify, const std::string& newValue, const PD_URI& predString )
1651 {
1652 PD_DocumentRDFMutationHandle m = createMutation();
1653 updateTriple( m, toModify, newValue, predString );
1654 m->commit();
1655 }
1656
1657 void
updateTriple(time_t & toModify,time_t newValue,const PD_URI & predString)1658 PD_RDFSemanticItem::updateTriple( time_t& toModify, time_t newValue, const PD_URI& predString )
1659 {
1660 PD_DocumentRDFMutationHandle m = createMutation();
1661 updateTriple( m, toModify, newValue, predString );
1662 m->commit();
1663 }
1664
1665 void
updateTriple(double & toModify,double newValue,const PD_URI & predString)1666 PD_RDFSemanticItem::updateTriple( double& toModify, double newValue, const PD_URI& predString )
1667 {
1668 PD_DocumentRDFMutationHandle m = createMutation();
1669 updateTriple( m, toModify, newValue, predString );
1670 m->commit();
1671 }
1672
updateTriple_remove(PD_DocumentRDFMutationHandle m,const PD_URI & toModify,const PD_URI & predString,const PD_URI & explicitLinkingSubject)1673 void PD_RDFSemanticItem::updateTriple_remove( PD_DocumentRDFMutationHandle m,
1674 const PD_URI& toModify,
1675 const PD_URI& predString,
1676 const PD_URI& explicitLinkingSubject )
1677 {
1678 PD_URI pred( predString );
1679 m->remove( explicitLinkingSubject, pred, PD_Literal(toModify.toString()) );
1680
1681 //
1682 // Typeless remove, I found that if a object literal did not
1683 // stipulate its type in the input RDF, just using
1684 // remove() above might not pick it up. So the below code
1685 // looks through all statements with subj+pred and checks typeless
1686 // string identity of the object() and removes it if strings match.
1687 //
1688 PD_ObjectList objects = m_rdf->getObjects( explicitLinkingSubject, pred );
1689 std::list< PD_RDFStatement > removeList;
1690 for( PD_ObjectList::iterator it = objects.begin(); it != objects.end(); ++it )
1691 {
1692 PD_Object obj = *it;
1693 PD_RDFStatement s( explicitLinkingSubject, pred, obj );
1694
1695 if( obj.toString() == toModify.toString())
1696 {
1697 removeList.push_back( s );
1698 }
1699
1700 // //
1701 // // Sometimes the object value is serialized as 51.47026 or
1702 // // 5.1470260000e+01. There are also slight rounding errors
1703 // // which are introduced that complicate comparisons.
1704 // //
1705 // if (toModify.isDouble())
1706 // {
1707 // removeList.push_back( s );
1708 // }
1709 }
1710
1711 m->remove( removeList );
1712 }
1713
1714
updateTriple_add(PD_DocumentRDFMutationHandle m,const PD_URI & toModify,const PD_URI & predString,const PD_URI & explicitLinkingSubject)1715 void PD_RDFSemanticItem::updateTriple_add( PD_DocumentRDFMutationHandle m,
1716 const PD_URI& toModify,
1717 const PD_URI& predString,
1718 const PD_URI& explicitLinkingSubject )
1719 {
1720 if( toModify.empty() )
1721 return;
1722 PD_URI pred( predString );
1723 m->add( explicitLinkingSubject, pred, PD_Literal(toModify.toString()), context() );
1724 }
1725
1726
1727
1728 PD_URI
createUUIDNode()1729 PD_RDFSemanticItem::createUUIDNode()
1730 {
1731 std::string uuid = XAP_App::getApp()->createUUIDString();
1732 return PD_URI( uuid );
1733
1734 }
1735
1736 void
importFromFile(const std::string & filename_const)1737 PD_RDFSemanticItem::importFromFile( const std::string& filename_const )
1738 {
1739 std::string filename = getImportFromFileName( filename_const, getImportTypes() );
1740 std::ifstream iss( filename.c_str() );
1741 importFromData( iss, m_rdf );
1742 }
1743
1744 PD_RDFSemanticItemHandle
createSemanticItem(PD_DocumentRDFHandle rdf,const std::string & semanticClass)1745 PD_RDFSemanticItem::createSemanticItem( PD_DocumentRDFHandle rdf, const std::string& semanticClass )
1746 {
1747 PD_ResultBindings_t b;
1748 b.push_back( std::map< std::string, std::string >() );
1749 PD_ResultBindings_t::iterator it = b.begin();
1750 return createSemanticItem( rdf, it, semanticClass );
1751 }
1752
1753 PD_RDFSemanticItemHandle
createSemanticItem(PD_DocumentRDFHandle rdf,PD_ResultBindings_t::iterator it,const std::string & semanticClass)1754 PD_RDFSemanticItem::createSemanticItem( PD_DocumentRDFHandle rdf,
1755 PD_ResultBindings_t::iterator it,
1756 const std::string& semanticClass )
1757 {
1758 if (semanticClass == "Contact")
1759 {
1760 return PD_RDFSemanticItemHandle( PD_DocumentRDF::getSemanticItemFactory()->createContact( rdf, it ) );
1761 }
1762 if (semanticClass == "Event")
1763 {
1764 return PD_RDFSemanticItemHandle( PD_DocumentRDF::getSemanticItemFactory()->createEvent( rdf, it ));
1765 }
1766 #ifdef WITH_CHAMPLAIN
1767 if (semanticClass == "Location")
1768 {
1769 return PD_RDFSemanticItemHandle( PD_DocumentRDF::getSemanticItemFactory()->createLocation( rdf, it ));
1770 }
1771 #endif
1772 return PD_RDFSemanticItemHandle();
1773 }
1774
1775 void
showEditorWindow(const PD_RDFSemanticItems & cl)1776 PD_RDFSemanticItem::showEditorWindow( const PD_RDFSemanticItems& cl )
1777 {
1778 UT_DEBUG_ONLY_ARG(cl);
1779
1780 UT_DEBUGMSG(("showEditorWindow(base) list... sz:%lu\n", (long unsigned)cl.size() ));
1781 }
1782
1783
1784 void
showEditorWindow(const PD_RDFSemanticItemHandle & c)1785 PD_RDFSemanticItem::showEditorWindow( const PD_RDFSemanticItemHandle& c )
1786 {
1787 UT_DEBUG_ONLY_ARG(c);
1788
1789 UT_DEBUGMSG(("showEditorWindow(base) name:%s linksubj:%s\n",
1790 c->name().c_str(), c->linkingSubject().toString().c_str() ));
1791 }
1792
1793 void
importFromDataComplete(std::istream &,PD_DocumentRDFHandle,PD_DocumentRDFMutationHandle,PD_DocumentRange *)1794 PD_RDFSemanticItem::importFromDataComplete( std::istream& /*iss*/,
1795 PD_DocumentRDFHandle /*rdf*/,
1796 PD_DocumentRDFMutationHandle /*m*/,
1797 PD_DocumentRange* /*pDocRange*/ )
1798 {
1799 UT_DEBUGMSG(("importFromDataComplete(base)\n"));
1800 }
1801
1802 std::string
getImportFromFileName(const std::string &,std::list<std::pair<std::string,std::string>>) const1803 PD_RDFSemanticItem::getImportFromFileName( const std::string& /*filename_const*/,
1804 std::list< std::pair< std::string, std::string> > /*types*/ ) const
1805 {
1806 return "";
1807 }
1808 std::string
getExportToFileName(const std::string &,std::string,std::list<std::pair<std::string,std::string>>) const1809 PD_RDFSemanticItem::getExportToFileName( const std::string& /*filename_const*/,
1810 std::string /*defaultExtension*/,
1811 std::list< std::pair< std::string, std::string> > /*types*/ ) const
1812 {
1813 return "";
1814 }
1815
1816 /***********/
1817 /***********/
1818 /***********/
1819
PD_RDFContact(PD_DocumentRDFHandle rdf,PD_ResultBindings_t::iterator & it)1820 PD_RDFContact::PD_RDFContact( PD_DocumentRDFHandle rdf, PD_ResultBindings_t::iterator& it )
1821 : PD_RDFSemanticItem( rdf, it )
1822 {
1823 m_linkingSubject = PD_URI( bindingAsString( it, "person") );
1824 m_nick = optionalBindingAsString( it, "nick");
1825 m_email = optionalBindingAsString( it, "email");
1826 m_homePage = optionalBindingAsString( it, "homepage");
1827 m_imageUrl = optionalBindingAsString( it, "img");
1828 m_phone = optionalBindingAsString( it, "phone");
1829 m_jabberID = optionalBindingAsString( it, "jabberid");
1830 }
1831
1832
~PD_RDFContact()1833 PD_RDFContact::~PD_RDFContact()
1834 {
1835 }
1836
1837
1838 std::string
getDisplayLabel() const1839 PD_RDFContact::getDisplayLabel() const
1840 {
1841 return "Contact";
1842 }
1843
1844 void
setupStylesheetReplacementMapping(std::map<std::string,std::string> & m)1845 PD_RDFContact::setupStylesheetReplacementMapping( std::map< std::string, std::string >& m )
1846 {
1847 m["%NICK%"] = m_nick;
1848 m["%HOMEPAGE%"] = m_homePage;
1849 m["%PHONE%"] = m_phone;
1850 m["%EMAIL%"] = m_email;
1851 }
1852
1853
1854 PD_RDFSemanticStylesheets
stylesheets() const1855 PD_RDFContact::stylesheets() const
1856 {
1857 PD_RDFSemanticStylesheets ret;
1858 ret.push_back(
1859 PD_RDFSemanticStylesheetHandle(
1860 new PD_RDFSemanticStylesheet("143c1ba3-d7bb-440b-8528-7f07d2eff5f2", RDF_SEMANTIC_STYLESHEET_CONTACT_NAME, "%NAME%")));
1861 ret.push_back(
1862 PD_RDFSemanticStylesheetHandle(
1863 new PD_RDFSemanticStylesheet("2fad34d1-42a0-4b10-b17e-a87db5208f6d", RDF_SEMANTIC_STYLESHEET_CONTACT_NICK, "%NICK%")));
1864 ret.push_back(
1865 PD_RDFSemanticStylesheetHandle(
1866 new PD_RDFSemanticStylesheet("0dd5878d-95c5-47e5-a777-63ec36da3b9a", RDF_SEMANTIC_STYLESHEET_CONTACT_NAME_PHONE, "%NAME%, %PHONE%")));
1867 ret.push_back(
1868 PD_RDFSemanticStylesheetHandle(
1869 new PD_RDFSemanticStylesheet("9cbeb4a6-34c5-49b2-b3ef-b94277db0c59", RDF_SEMANTIC_STYLESHEET_CONTACT_NICK_PHONE, "%NICK%, %PHONE%")));
1870 ret.push_back(
1871 PD_RDFSemanticStylesheetHandle(
1872 new PD_RDFSemanticStylesheet("47025a4a-5da5-4a32-8d89-14c03658631d", RDF_SEMANTIC_STYLESHEET_CONTACT_NAME_HOMEPAGE_PHONE, "%NAME%, (%HOMEPAGE%), %PHONE%")));
1873 return ret;
1874 }
1875
1876 std::string
className() const1877 PD_RDFContact::className() const
1878 {
1879 return "Contact";
1880 }
1881
1882
1883
1884
1885 #ifdef WITH_EVOLUTION_DATA_SERVER
1886 #include <libebook/libebook.h>
1887
get(EVCard * c,const char * v)1888 static std::string get( EVCard* c, const char* v )
1889 {
1890 EVCardAttribute* a = e_vcard_get_attribute( c, v );
1891 UT_DEBUGMSG((" cvard.group:%s v:%s\n", e_vcard_attribute_get_group( a ), v ));
1892
1893 if( a && e_vcard_attribute_is_single_valued(a) )
1894 {
1895 return e_vcard_attribute_get_value(a);
1896 }
1897 return "";
1898 }
1899
set(EVCard * c,const char * k,const std::string & v)1900 static void set( EVCard* c, const char* k, const std::string& v )
1901 {
1902 EVCardAttribute* a = e_vcard_get_attribute( c, k );
1903 if( !a )
1904 {
1905 a = e_vcard_attribute_new( 0, k );
1906 e_vcard_append_attribute( c, a );
1907 }
1908
1909 if( a )
1910 {
1911 e_vcard_attribute_add_value( a, v.c_str() );
1912 }
1913 }
1914 #endif
1915
1916 std::list< std::pair< std::string, std::string> >
getImportTypes() const1917 PD_RDFContact::getImportTypes() const
1918 {
1919 std::list< std::pair< std::string, std::string> > types;
1920 types.push_back( std::make_pair( "VCard File", "vcf" ));
1921 return types;
1922 }
1923
1924 void
importFromData(std::istream & iss,PD_DocumentRDFHandle rdf,PD_DocumentRange * pDocRange)1925 PD_RDFContact::importFromData( std::istream& iss, PD_DocumentRDFHandle rdf, PD_DocumentRange * pDocRange )
1926 {
1927 #ifdef WITH_EVOLUTION_DATA_SERVER
1928
1929 std::string vcard = StreamToString( iss );
1930 UT_DEBUGMSG(("trying to get card for data:%s\n", vcard.c_str() ));
1931 if( EVCard* c = e_vcard_new_from_string( vcard.c_str() ) )
1932 {
1933 std::string textrep = "";
1934 typedef std::list< const char* > charplist_t;
1935 charplist_t textreplist;
1936 textreplist.push_back( EVC_EMAIL );
1937 textreplist.push_back( EVC_FN );
1938 textreplist.push_back( EVC_NICKNAME );
1939 textreplist.push_back( EVC_UID );
1940 for( charplist_t::iterator iter = textreplist.begin();
1941 iter != textreplist.end(); ++iter )
1942 {
1943 textrep = get( c, *iter );
1944 if( !textrep.empty() )
1945 break;
1946 }
1947 UT_DEBUGMSG(("have card!\n"));
1948
1949 std::string fn = get( c, EVC_FN );
1950 std::string uid = get( c, EVC_UID );
1951 std::string xmlid = rdf->makeLegalXMLID( fn + "_" + uid );
1952 std::string email = get( c, EVC_EMAIL );
1953 UT_DEBUGMSG(("uid:%s xmlid:%s\n", uid.c_str(), xmlid.c_str() ));
1954
1955 m_name = fn;
1956 m_nick = get( c, EVC_NICKNAME );
1957 m_email = email;
1958 m_phone = get( c, EVC_TEL );
1959 m_jabberID = get( c, EVC_X_JABBER );
1960
1961 // std::pair< PT_DocPosition, PT_DocPosition > se = insertTextWithXMLID( textrep, xmlid );
1962 // PT_DocPosition startpos = se.first;
1963 // PT_DocPosition endpos = se.second;
1964
1965 std::string uuid = "http://abicollab.net/rdf/foaf#" + uid;
1966 m_linkingSubject = PD_URI( uuid );
1967 XAP_Frame* lff = XAP_App::getApp()->getLastFocussedFrame();
1968 if(lff)
1969 {
1970 // FV_View * pView = static_cast<FV_View*>( lff->getCurrentView() );
1971 // std::pair< PT_DocPosition, PT_DocPosition > se = insert( pView );
1972 // PT_DocPosition startpos = se.first;
1973 // PT_DocPosition endpos = se.second;
1974 }
1975
1976 // PD_DocumentRDFMutationHandle m = rdf->createMutation();
1977 // m->add( PD_URI(uuid),
1978 // PD_URI("http://docs.oasis-open.org/opendocument/meta/package/common#idref"),
1979 // PD_Literal( xmlid ) );
1980 // // m->add( PD_URI(uuid),
1981 // // PD_URI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
1982 // // PD_Object("http://xmlns.com/foaf/0.1/Person") );
1983 // // addFoafProp( m, c, EVC_TEL, uuidnode, "phone" );
1984 // // addFoafProp( m, c, EVC_NICKNAME, uuidnode, "nick" );
1985 // // addFoafProp( m, c, EVC_FN, uuidnode, "name" );
1986 // // addFoafProp( m, c, EVC_N, uuidnode, "givenName" );
1987 // // addFoafProp( m, c, EVC_X_JABBER, uuidnode, "jabberID" );
1988
1989 PD_DocumentRDFMutationHandle m = rdf->createMutation();
1990 importFromDataComplete( iss, rdf, m, pDocRange );
1991 m->commit();
1992 }
1993 #else
1994 UT_UNUSED(iss);
1995 UT_UNUSED(rdf);
1996 UT_UNUSED(pDocRange);
1997 #endif
1998 }
1999
2000
2001
2002 std::list< std::pair< std::string, std::string> >
getExportTypes() const2003 PD_RDFContact::getExportTypes() const
2004 {
2005 std::list< std::pair< std::string, std::string> > ret;
2006 ret.push_back( std::make_pair( "VCard File", "vcf" ));
2007 return ret;
2008 }
2009
2010 std::string
getDefaultExtension() const2011 PD_RDFContact::getDefaultExtension() const
2012 {
2013 return ".vcf";
2014 }
2015
2016
2017 void
exportToFile(const std::string & filename_const) const2018 PD_RDFContact::exportToFile( const std::string& filename_const ) const
2019 {
2020 std::string filename = getExportToFileName( filename_const,
2021 ".vcf",
2022 getExportTypes() );
2023
2024 UT_DEBUGMSG(( "saving vcard to file:%s\n", filename.c_str() ));
2025
2026 #ifdef WITH_EVOLUTION_DATA_SERVER
2027
2028 if( EVCard* c = e_vcard_new() )
2029 {
2030 set( c, EVC_FN, m_name );
2031 set( c, EVC_UID, m_linkingSubject.toString() );
2032 set( c, EVC_EMAIL, m_email );
2033 set( c, EVC_NICKNAME, m_nick );
2034 set( c, EVC_TEL, m_phone );
2035 set( c, EVC_X_JABBER, m_jabberID );
2036
2037 gchar* data = e_vcard_to_string( c, EVC_FORMAT_VCARD_30 );
2038 UT_DEBUGMSG(( "saving vcard to file:%s vcard.len:%ld\n", filename.c_str(), strlen(data) ));
2039 std::ofstream oss( filename.c_str() );
2040 oss.write( data, strlen(data) );
2041 oss.flush();
2042 oss.close();
2043 g_free(data);
2044 }
2045
2046 #endif
2047 }
2048
2049 /******************************/
2050 /******************************/
2051 /******************************/
2052
2053
2054 #ifdef WITH_LIBICAL
2055 extern "C" {
2056 #include <libical/ical.h>
2057 };
2058
2059
2060 #if 0
2061 // static std::string tostr( time_t v )
2062 // {
2063 // std::stringstream ss;
2064 // ss << v;
2065 // return ss.str();
2066 // }
2067
2068
2069 static void addCalProp( PD_DocumentRDFMutationHandle m,
2070 const PD_URI& uuidnode,
2071 const std::string& predend,
2072 const std::string& value )
2073 {
2074 std::string predBase = "http://www.w3.org/2002/12/cal/icaltzd#";
2075 m->add( uuidnode,
2076 PD_URI(predBase + predend),
2077 PD_Literal( value ) );
2078 }
2079 static void addCalPropSZ( PD_DocumentRDFMutationHandle m,
2080 const PD_URI& uuidnode,
2081 const std::string& predend,
2082 const char* value )
2083 {
2084 std::string predBase = "http://www.w3.org/2002/12/cal/icaltzd#";
2085 if( value )
2086 {
2087 addCalProp( m, uuidnode, predend, (std::string)value );
2088 }
2089 }
2090
2091 #endif
2092 #endif
2093
2094
PD_RDFEvent(PD_DocumentRDFHandle rdf,PD_ResultBindings_t::iterator & it)2095 PD_RDFEvent::PD_RDFEvent( PD_DocumentRDFHandle rdf, PD_ResultBindings_t::iterator& it )
2096 : PD_RDFSemanticItem( rdf, it )
2097 {
2098 m_linkingSubject = PD_URI( bindingAsString( it, "ev") );
2099 m_summary = optionalBindingAsString( it, "summary");
2100 m_location = optionalBindingAsString( it, "location");
2101 m_uid = optionalBindingAsString( it, "uid");
2102 m_desc = optionalBindingAsString( it, "description");
2103 m_dtstart = parseTimeString(optionalBindingAsString( it, "dtstart"));
2104 m_dtend = parseTimeString(optionalBindingAsString( it, "dtend"));
2105 if( m_name.empty() )
2106 m_name = m_uid;
2107 }
2108
~PD_RDFEvent()2109 PD_RDFEvent::~PD_RDFEvent()
2110 {
2111 }
2112
2113 void
setupStylesheetReplacementMapping(std::map<std::string,std::string> & m)2114 PD_RDFEvent::setupStylesheetReplacementMapping( std::map< std::string, std::string >& m )
2115 {
2116 m["%UID%"] = m_uid;
2117 m["%DESCRIPTION%"] = m_desc;
2118 m["%DESC%"] = m_desc;
2119 m["%SUMMARY%"] = m_summary;
2120 m["%LOCATION%"] = m_location;
2121 m["%START%"] = toTimeString(m_dtstart);
2122 m["%END%"] = toTimeString(m_dtend);
2123 }
2124
2125 PD_RDFSemanticStylesheets
stylesheets() const2126 PD_RDFEvent::stylesheets() const
2127 {
2128 PD_RDFSemanticStylesheets ret;
2129 ret.push_back(
2130 PD_RDFSemanticStylesheetHandle(
2131 new PD_RDFSemanticStylesheet("92f5d6c5-2c3a-4988-9646-2f29f3731f89",
2132 RDF_SEMANTIC_STYLESHEET_EVENT_NAME, "%NAME%")));
2133 ret.push_back(
2134 PD_RDFSemanticStylesheetHandle(
2135 new PD_RDFSemanticStylesheet("b4817ce4-d2c3-4ed3-bc5a-601010b33363",
2136 RDF_SEMANTIC_STYLESHEET_EVENT_SUMMARY, "%SUMMARY%")));
2137 ret.push_back(
2138 PD_RDFSemanticStylesheetHandle(
2139 new PD_RDFSemanticStylesheet("853242eb-031c-4a36-abb2-7ef1881c777e",
2140 RDF_SEMANTIC_STYLESHEET_EVENT_SUMMARY_LOCATION, "%SUMMARY%, %LOCATION%")));
2141 ret.push_back(
2142 PD_RDFSemanticStylesheetHandle(
2143 new PD_RDFSemanticStylesheet("2d6b87a8-23be-4b61-a881-876177812ad4",
2144 RDF_SEMANTIC_STYLESHEET_EVENT_SUMMARY_LOCATION_TIMES, "%SUMMARY%, %LOCATION%, %START%")));
2145 ret.push_back(
2146 PD_RDFSemanticStylesheetHandle(
2147 new PD_RDFSemanticStylesheet("115e3ceb-6bc8-445c-a932-baee09686895",
2148 RDF_SEMANTIC_STYLESHEET_EVENT_SUMMARY_TIMES, "%SUMMARY%, %START%")));
2149 return ret;
2150 }
2151
2152 std::string
className() const2153 PD_RDFEvent::className() const
2154 {
2155 return "Event";
2156 }
2157
2158 std::list< std::pair< std::string, std::string> >
getImportTypes() const2159 PD_RDFEvent::getImportTypes() const
2160 {
2161 std::list< std::pair< std::string, std::string> > types;
2162 types.push_back( std::make_pair( "ICalendar files", "ics" ));
2163 return types;
2164 }
2165
2166 std::list< std::pair< std::string, std::string> >
getExportTypes() const2167 PD_RDFEvent::getExportTypes() const
2168 {
2169 std::list< std::pair< std::string, std::string> > types;
2170 types.push_back( std::make_pair( "ICalendar files", "ics" ));
2171 return types;
2172 }
2173
2174 std::string
getDisplayLabel() const2175 PD_RDFEvent::getDisplayLabel() const
2176 {
2177 return "Event";
2178 }
2179
2180
2181 #ifdef WITH_LIBICAL
setFromString(std::string & s,const char * input)2182 static void setFromString( std::string& s, const char* input )
2183 {
2184 if( input )
2185 s = input;
2186 else
2187 s = "";
2188 }
2189 #endif
2190
2191
2192 void
importFromData(std::istream & iss,PD_DocumentRDFHandle rdf,PD_DocumentRange * pDocRange)2193 PD_RDFEvent::importFromData( std::istream& iss, PD_DocumentRDFHandle rdf, PD_DocumentRange * pDocRange )
2194 {
2195 #ifdef WITH_LIBICAL
2196
2197 std::string data = StreamToString(iss);
2198 UT_DEBUGMSG(("trying to get calendar for data:%s\n", data.c_str() ));
2199
2200 if( icalcomponent* c = icalcomponent_new_from_string( data.c_str() ) )
2201 {
2202 const char* zdesc = icalcomponent_get_description( c );
2203 const char* zloc = icalcomponent_get_location( c );
2204 const char* zsummary = icalcomponent_get_summary( c );
2205 const char* zuid = icalcomponent_get_uid( c );
2206 struct icaltimetype zdtstart = icalcomponent_get_dtstart( c );
2207 struct icaltimetype zdtend = icalcomponent_get_dtend( c );
2208
2209 std::string xmlid;
2210 if( zsummary )
2211 xmlid += (std::string)"" + zsummary + "_";
2212 if( zuid )
2213 xmlid += zuid;
2214
2215 xmlid = rdf->makeLegalXMLID( xmlid );
2216
2217 setFromString( m_desc, zdesc );
2218 setFromString( m_location, zloc );
2219 setFromString( m_summary, zsummary );
2220 setFromString( m_uid, zuid );
2221 m_name = m_uid;
2222 m_dtstart = icaltime_as_timet( zdtstart );
2223 m_dtend = icaltime_as_timet( zdtend );
2224
2225
2226 std::string uuid = "http://abicollab.net/rdf/cal#" + xmlid;
2227 m_linkingSubject = PD_URI( uuid );
2228 XAP_Frame* lff = XAP_App::getApp()->getLastFocussedFrame();
2229 if(lff)
2230 {
2231 // FV_View * pView = static_cast<FV_View*>( lff->getCurrentView() );
2232 // std::pair< PT_DocPosition, PT_DocPosition > se = insert( pView );
2233 // PT_DocPosition startpos = se.first;
2234 // PT_DocPosition endpos = se.second;
2235 }
2236
2237 PD_DocumentRDFMutationHandle m = rdf->createMutation();
2238 importFromDataComplete( iss, rdf, m, pDocRange );
2239 m->commit();
2240 }
2241 #else
2242 UT_UNUSED(iss);
2243 UT_UNUSED(rdf);
2244 UT_UNUSED(pDocRange);
2245 #endif
2246 }
2247
2248 std::string
getDefaultExtension() const2249 PD_RDFEvent::getDefaultExtension() const
2250 {
2251 return ".ical";
2252 }
2253
2254 void
exportToFile(const std::string & filename_const) const2255 PD_RDFEvent::exportToFile( const std::string& filename_const ) const
2256 {
2257 std::string filename = getExportToFileName( filename_const,
2258 ".ical",
2259 getExportTypes() );
2260
2261 UT_DEBUGMSG(( "saving ical to file:%s\n", filename.c_str() ));
2262
2263 #ifdef WITH_LIBICAL
2264
2265 if( icalcomponent* c = icalcomponent_new( ICAL_VEVENT_COMPONENT ) )
2266 {
2267 icalcomponent_set_uid( c, m_uid.c_str() );
2268 icalcomponent_set_location( c, m_location.c_str() );
2269 icalcomponent_set_description( c, m_desc.c_str() );
2270 icalcomponent_set_dtstart( c, icaltime_from_timet_with_zone( m_dtstart, 0, NULL ) );
2271 icalcomponent_set_dtend( c, icaltime_from_timet_with_zone( m_dtend, 0, NULL ) );
2272
2273 char* data = icalcomponent_as_ical_string( c );
2274 std::ofstream oss( filename.c_str() );
2275 oss.write( data, strlen(data) );
2276 oss.flush();
2277 oss.close();
2278 }
2279 #endif
2280
2281 }
2282
2283
2284 /******************************/
2285 /******************************/
2286 /******************************/
2287
2288
2289
2290
2291
2292 std::list< std::pair< std::string, std::string> >
getImportTypes() const2293 PD_RDFLocation::getImportTypes() const
2294 {
2295 std::list< std::pair< std::string, std::string> > types;
2296 types.push_back( std::make_pair( "KML files", "kml" ));
2297 return types;
2298 }
2299
2300 std::list< std::pair< std::string, std::string> >
getExportTypes() const2301 PD_RDFLocation::getExportTypes() const
2302 {
2303 std::list< std::pair< std::string, std::string> > types;
2304 types.push_back( std::make_pair( "KML files", "kml" ));
2305 return types;
2306 }
2307
PD_RDFLocation(PD_DocumentRDFHandle rdf,PD_ResultBindings_t::iterator & it,bool isGeo84)2308 PD_RDFLocation::PD_RDFLocation( PD_DocumentRDFHandle rdf, PD_ResultBindings_t::iterator& it, bool isGeo84 )
2309 : PD_RDFSemanticItem( rdf, it )
2310 , m_isGeo84( isGeo84 )
2311 {
2312 m_linkingSubject = PD_URI( bindingAsString( it, "geo") );
2313
2314 m_name = optionalBindingAsString( it, "name");
2315 m_uid = optionalBindingAsString( it, "uid");
2316 m_desc = optionalBindingAsString( it, "desc");
2317 m_dlat = toType<double>(optionalBindingAsString( it, "lat"));
2318 m_dlong = toType<double>(optionalBindingAsString( it, "long"));
2319 m_joiner = PD_Object(optionalBindingAsString( it, "joiner"));
2320 if( m_name.empty() )
2321 m_name = m_uid;
2322 if( m_name.empty() )
2323 {
2324 m_name = tostr(m_dlat) + "_" + tostr(m_dlong);
2325 if( m_uid.empty() )
2326 m_uid = m_name;
2327 }
2328
2329 UT_DEBUGMSG(("PD_RDFLocation() name:%s long:%f lat:%f geo84:%d\n", m_name.c_str(), m_dlat, m_dlong, isGeo84 ));
2330 }
2331
~PD_RDFLocation()2332 PD_RDFLocation::~PD_RDFLocation()
2333 {
2334 }
2335
2336 void
setupStylesheetReplacementMapping(std::map<std::string,std::string> & m)2337 PD_RDFLocation::setupStylesheetReplacementMapping( std::map< std::string, std::string >& m )
2338 {
2339 m["%UID%"] = m_uid;
2340 m["%DESCRIPTION%"] = m_desc;
2341 m["%DESC%"] = m_desc;
2342 m["%LAT%"] = tostr(m_dlat);
2343 m["%LONG%"] = tostr(m_dlong);
2344 m["%DLAT%"] = tostr(m_dlat);
2345 m["%DLONG%"] = tostr(m_dlong);
2346 }
2347
2348 PD_RDFSemanticStylesheets
stylesheets() const2349 PD_RDFLocation::stylesheets() const
2350 {
2351 PD_RDFSemanticStylesheets ret;
2352 ret.push_back(
2353 PD_RDFSemanticStylesheetHandle(
2354 new PD_RDFSemanticStylesheet("33314909-7439-4aa1-9a55-116bb67365f0", RDF_SEMANTIC_STYLESHEET_LOCATION_NAME, "%NAME%")));
2355 ret.push_back(
2356 PD_RDFSemanticStylesheetHandle(
2357 new PD_RDFSemanticStylesheet("34584133-52b0-449f-8b7b-7f1ef5097b9a",
2358 RDF_SEMANTIC_STYLESHEET_LOCATION_NAME_LATLONG,
2359 "%NAME%, %DLAT%, %DLONG%")));
2360 return ret;
2361 }
2362
2363 std::string
className() const2364 PD_RDFLocation::className() const
2365 {
2366 return "Location";
2367 }
2368
2369
2370 std::string
getDisplayLabel() const2371 PD_RDFLocation::getDisplayLabel() const
2372 {
2373 return "Location";
2374 }
2375
2376 void
importFromData(std::istream &,PD_DocumentRDFHandle,PD_DocumentRange *)2377 PD_RDFLocation::importFromData( std::istream& /*iss*/,
2378 PD_DocumentRDFHandle /*rdf*/,
2379 PD_DocumentRange * /*pDocRange*/ )
2380 {
2381 UT_DEBUGMSG(( "FIXME: importFromData()\n" ));
2382 }
2383
2384 std::string
getDefaultExtension() const2385 PD_RDFLocation::getDefaultExtension() const
2386 {
2387 return ".kml";
2388 }
2389
2390 void
exportToFile(const std::string & filename_const) const2391 PD_RDFLocation::exportToFile( const std::string& filename_const ) const
2392 {
2393 std::string filename = getExportToFileName( filename_const, ".kml", getExportTypes() );
2394 UT_DEBUGMSG(( "Saving KML to file:%s\n", filename.c_str() ));
2395
2396
2397 std::ofstream xmlss( filename.c_str() );
2398 xmlss << "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
2399 << "<kml xmlns=\"http://www.opengis.net/kml/2.2\" > \n"
2400 << " \n"
2401 << "<Placemark> \n"
2402 << " <name>" << name() << "</name> \n"
2403 << " <LookAt> \n"
2404 << " <longitude>" << m_dlong << "</longitude> \n"
2405 << " <latitude>" << m_dlat << "</latitude> \n"
2406 << " </LookAt> \n"
2407 << "</Placemark> \n"
2408 << "</kml>\n";
2409 xmlss.flush();
2410 xmlss.close();
2411 }
2412
2413 std::set< std::string >
getXMLIDs() const2414 PD_RDFLocation::getXMLIDs() const
2415 {
2416 std::set< std::string > ret;
2417
2418 std::stringstream ss;
2419 ss << "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " << std::endl
2420 << "prefix foaf: <http://xmlns.com/foaf/0.1/> " << std::endl
2421 << "prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#> " << std::endl
2422 << "prefix geo84: <http://www.w3.org/2003/01/geo/wgs84_pos#>" << std::endl
2423 << "" << std::endl
2424 << "select distinct ?s ?p ?o ?xmlid" << std::endl
2425 << "where { " << std::endl
2426 << " ?s pkg:idref ?xmlid ." << std::endl
2427 << " ?s ?p ?o " << std::endl
2428 << " . filter( str(?o) = \"" << m_linkingSubject.toString() << "\" )" << std::endl
2429 << "}" << std::endl;
2430 std::set<std::string> uniqfilter;
2431 PD_RDFQuery q( getRDF(), getRDF() );
2432 PD_ResultBindings_t bindings = q.executeQuery( ss.str() );
2433 for( PD_ResultBindings_t::iterator iter = bindings.begin(); iter != bindings.end(); ++iter )
2434 {
2435 std::map< std::string, std::string > d = *iter;
2436 std::string xmlid = d["xmlid"];
2437 if (uniqfilter.count(xmlid))
2438 continue;
2439 uniqfilter.insert(xmlid);
2440
2441 if( !xmlid.empty() )
2442 ret.insert( xmlid );
2443 UT_DEBUGMSG(("PD_RDFLocation::getXMLIDs() xmlid:%s\n", xmlid.c_str() ));
2444 }
2445
2446 return ret;
2447 }
2448
2449
2450
2451 /************************************************************/
2452 /************************************************************/
2453 /************************************************************/
2454
2455
2456
2457
2458 /************************************************************/
2459 /************************************************************/
2460 /************************************************************/
2461
2462
2463 std::pair< PT_DocPosition, PT_DocPosition >
insert(PD_DocumentRDFMutationHandle m,FV_View *)2464 PD_RDFSemanticItem::insert( PD_DocumentRDFMutationHandle m, FV_View* /*pView*/ )
2465 {
2466 std::string xmlid = m_rdf->makeLegalXMLID( name() );
2467 std::pair< PT_DocPosition, PT_DocPosition > se = insertTextWithXMLID( name(), xmlid );
2468 if (m_linkingSubject.toString().empty())
2469 {
2470 std::string uuid = XAP_App::getApp()->createUUIDString();
2471 m_linkingSubject = uuid;
2472 }
2473 m->add( m_linkingSubject,
2474 PD_URI("http://docs.oasis-open.org/opendocument/meta/package/common#idref"),
2475 PD_Literal( xmlid ) );
2476 return se;
2477 }
2478
2479
2480
2481 std::pair< PT_DocPosition, PT_DocPosition >
insert(FV_View * pView)2482 PD_RDFSemanticItem::insert( FV_View* pView )
2483 {
2484 PD_DocumentRDFMutationHandle m = m_rdf->createMutation();
2485 std::pair< PT_DocPosition, PT_DocPosition > ret = insert( m, pView );
2486 m->commit();
2487 return ret;
2488 }
2489
2490
2491
2492
2493 std::list< std::string >
getClassNames()2494 PD_RDFSemanticItem::getClassNames()
2495 {
2496 std::list< std::string > ret;
2497 ret.push_back( "Contact" );
2498 ret.push_back( "Event" );
2499 ret.push_back( "Location" );
2500 return ret;
2501 }
2502
2503 void
setupStylesheetReplacementMapping(std::map<std::string,std::string> &)2504 PD_RDFSemanticItem::setupStylesheetReplacementMapping( std::map< std::string, std::string >& /*m*/ )
2505 {
2506 }
2507
2508
2509 PD_RDFSemanticStylesheetHandle
findStylesheetByUuid(const std::string & uuid) const2510 PD_RDFSemanticItem::findStylesheetByUuid(const std::string &uuid) const
2511 {
2512 PD_RDFSemanticStylesheetHandle ret;
2513 if( uuid.empty() )
2514 return ret;
2515
2516 PD_RDFSemanticStylesheets ssl = stylesheets();
2517 for( PD_RDFSemanticStylesheets::iterator iter = ssl.begin(); iter != ssl.end(); ++iter )
2518 {
2519 PD_RDFSemanticStylesheetHandle ss = *iter;
2520 if ( ss->uuid() == uuid )
2521 {
2522 return ss;
2523 }
2524 }
2525 return ret;
2526 }
2527
2528
2529 PD_RDFSemanticStylesheetHandle
findStylesheetByName(const std::string &,const std::string & n) const2530 PD_RDFSemanticItem::findStylesheetByName(const std::string & /*sheetType*/, const std::string &n) const
2531 {
2532 return findStylesheetByName( stylesheets(), n );
2533 }
2534
2535
2536 PD_RDFSemanticStylesheetHandle
findStylesheetByName(const PD_RDFSemanticStylesheets & ssl,const std::string & n) const2537 PD_RDFSemanticItem::findStylesheetByName(const PD_RDFSemanticStylesheets& ssl, const std::string &n) const
2538 {
2539 PD_RDFSemanticStylesheetHandle ret;
2540 if( n.empty() )
2541 return ret;
2542 for( PD_RDFSemanticStylesheets::const_iterator iter = ssl.begin(); iter != ssl.end(); ++iter )
2543 {
2544 PD_RDFSemanticStylesheetHandle ss = *iter;
2545 if ( ss->name() == n )
2546 {
2547 return ss;
2548 }
2549 }
2550 return ret;
2551
2552 }
2553
2554 std::string
getProperty(std::string subj,std::string pred,std::string defVal) const2555 PD_RDFSemanticItem::getProperty( std::string subj, std::string pred, std::string defVal ) const
2556 {
2557 PD_Object o = m_rdf->getObject( subj, pred );
2558 if( o.empty() )
2559 return defVal;
2560 return o.toString();
2561
2562 }
2563
2564
2565 PD_RDFSemanticStylesheetHandle
defaultStylesheet() const2566 PD_RDFSemanticItem::defaultStylesheet() const
2567 {
2568 std::string semanticClass = className();
2569 std::string name_ = getProperty( "http://calligra-suite.org/rdf/document/" + semanticClass,
2570 "http://calligra-suite.org/rdf/stylesheet",
2571 RDF_SEMANTIC_STYLESHEET_NAME );
2572 std::string type = getProperty( "http://calligra-suite.org/rdf/document/" + semanticClass,
2573 "http://calligra-suite.org/rdf/stylesheet-type",
2574 PD_RDFSemanticStylesheet::stylesheetTypeSystem() );
2575 std::string uuid = getProperty( "http://calligra-suite.org/rdf/document/" + semanticClass,
2576 "http://calligra-suite.org/rdf/stylesheet-uuid",
2577 "" );
2578
2579 PD_RDFSemanticStylesheetHandle ret = findStylesheetByUuid( uuid );
2580 if (!ret)
2581 {
2582 ret = findStylesheetByName( type, name_ );
2583 }
2584 if (!ret)
2585 {
2586 // The "name" stylesheet should always exist
2587 ret = findStylesheetByName( PD_RDFSemanticStylesheet::stylesheetTypeSystem(), RDF_SEMANTIC_STYLESHEET_NAME );
2588 }
2589 return ret;
2590
2591 }
2592
2593 void
relationAdd(PD_RDFSemanticItemHandle dst,RelationType rt)2594 PD_RDFSemanticItem::relationAdd( PD_RDFSemanticItemHandle dst, RelationType rt )
2595 {
2596 std::string predBase("http://xmlns.com/foaf/0.1/" );
2597 PD_URI pred( predBase + "knows");
2598
2599 PD_DocumentRDFMutationHandle m = m_rdf->createMutation();
2600 switch( rt )
2601 {
2602 case RELATION_FOAF_KNOWS:
2603 // symetric relation
2604 m->add( linkingSubject(), pred, PD_Object(dst->linkingSubject()) );
2605 m->add( dst->linkingSubject(), pred, PD_Object(linkingSubject()) );
2606 break;
2607 }
2608 m->commit();
2609 }
2610
2611 PD_RDFSemanticItems
relationFind(RelationType rt)2612 PD_RDFSemanticItem::relationFind( RelationType rt )
2613 {
2614 std::string predBase("http://xmlns.com/foaf/0.1/" );
2615 PD_URI pred( predBase + "knows");
2616
2617 switch( rt )
2618 {
2619 case RELATION_FOAF_KNOWS:
2620 pred = PD_URI( predBase + "knows");
2621 break;
2622 }
2623 UT_DEBUGMSG(("relationFind() this->linkingSubj:%s\n", linkingSubject().c_str() ));
2624
2625 std::set< std::string > xmlids;
2626 PD_ObjectList ol = m_rdf->getObjects( linkingSubject(), pred );
2627 for( PD_ObjectList::iterator iter = ol.begin(); iter != ol.end(); ++iter )
2628 {
2629 PD_URI linkingSubj = *iter;
2630 UT_DEBUGMSG(("relationFind() linkingSubj:%s\n", linkingSubj.c_str() ));
2631
2632 std::set< std::string > t = getXMLIDsForLinkingSubject( m_rdf, linkingSubj.toString() );
2633 UT_DEBUGMSG(("relationFind() t.sz:%ld\n", (long)t.size() ));
2634 xmlids.insert( t.begin(), t.end() );
2635 }
2636
2637 UT_DEBUGMSG(("relationFind() xmlids.sz:%ld\n", (long)xmlids.size() ));
2638 PD_RDFSemanticItems ret = m_rdf->getSemanticObjects( xmlids );
2639 return ret;
2640 }
2641
2642 std::set< std::string >
getXMLIDsForLinkingSubject(PD_DocumentRDFHandle rdf,const std::string & linkingSubj)2643 PD_RDFSemanticItem::getXMLIDsForLinkingSubject( PD_DocumentRDFHandle rdf, const std::string& linkingSubj )
2644 {
2645 std::set< std::string > ret;
2646
2647 std::stringstream ss;
2648 ss << "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " << std::endl
2649 << "prefix foaf: <http://xmlns.com/foaf/0.1/> " << std::endl
2650 << "prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#> " << std::endl
2651 << "prefix geo84: <http://www.w3.org/2003/01/geo/wgs84_pos#>" << std::endl
2652 << "" << std::endl
2653 << "select distinct ?s ?xmlid" << std::endl
2654 << "where { " << std::endl
2655 << " ?s pkg:idref ?xmlid " << std::endl
2656 << " . filter( str(?s) = \"" << linkingSubj << "\" )" << std::endl
2657 << "}" << std::endl;
2658 std::set<std::string> uniqfilter;
2659 PD_RDFQuery q( rdf, rdf );
2660 UT_DEBUGMSG(("getXMLIDsForLinkingSubject() sparql:%s\n", ss.str().c_str() ));
2661 PD_ResultBindings_t bindings = q.executeQuery( ss.str() );
2662 for( PD_ResultBindings_t::iterator iter = bindings.begin(); iter != bindings.end(); ++iter )
2663 {
2664 std::map< std::string, std::string > d = *iter;
2665 std::string xmlid = d["xmlid"];
2666 if (uniqfilter.count(xmlid))
2667 continue;
2668 uniqfilter.insert(xmlid);
2669 if( !xmlid.empty() )
2670 ret.insert( xmlid );
2671 }
2672 return ret;
2673 }
2674
2675
2676 /************************************************************/
2677 /************************************************************/
2678 /************************************************************/
2679
PD_RDFSemanticStylesheet(const std::string & _uuid,const std::string & _name,const std::string & _templateString,const std::string & _type,bool _isMutable)2680 PD_RDFSemanticStylesheet::PD_RDFSemanticStylesheet(
2681 const std::string &_uuid,
2682 const std::string &_name,
2683 const std::string &_templateString,
2684 const std::string &_type,
2685 bool _isMutable
2686 )
2687 : m_uuid(_uuid)
2688 , m_name(_name)
2689 , m_templateString(_templateString)
2690 , m_type(_type)
2691 , m_isMutable(_isMutable)
2692 {
2693 }
2694
2695
2696 void
format(PD_RDFSemanticItemHandle obj,FV_View * pView,const std::string & xmlid_const)2697 PD_RDFSemanticStylesheet::format( PD_RDFSemanticItemHandle obj, FV_View* pView, const std::string& xmlid_const )
2698 {
2699 PD_Document* pDoc = pView->getDocument();
2700 PD_DocumentRDFHandle rdf = obj->getRDF();
2701 std::string xmlid = xmlid_const;
2702 if( xmlid.empty() )
2703 {
2704 std::set< std::string > tmp;
2705 rdf->addRelevantIDsForPosition( tmp, pView->getPoint() );
2706 if( tmp.empty() )
2707 {
2708 UT_DEBUGMSG(("ss:format(no xmlid!) obj->name:%s\n", obj->name().c_str() ));
2709 return;
2710 }
2711 xmlid = *(tmp.begin());
2712 }
2713
2714 UT_DEBUGMSG(("ss:format() obj->name:%s\n", obj->name().c_str() ));
2715 UT_DEBUGMSG(("xmlid:%s pView:%p sheetname:%s\n", xmlid.c_str(), pView, name().c_str() ));
2716
2717 std::pair< PT_DocPosition, PT_DocPosition > p = rdf->getIDRange( xmlid );
2718 PT_DocPosition startpos = p.first + 1;
2719 PT_DocPosition endpos = p.second;
2720 if (!endpos)
2721 {
2722 UT_DEBUGMSG(("ss:format(invalid range!) obj->name:%s\n", obj->name().c_str() ));
2723 return;
2724 }
2725 UT_DEBUGMSG(("formating start:%d end:%d\n", startpos, endpos ));
2726
2727 // Grab the text that was there and remove it.
2728 pView->selectRange( startpos, endpos );
2729 pView->cmdCut();
2730 pView->setPoint( startpos );
2731
2732 std::string data = templateString();
2733 std::map< std::string, std::string > m;
2734 m["%NAME%"] = obj->name();
2735 obj->setupStylesheetReplacementMapping( m );
2736
2737 for( std::map< std::string, std::string >::iterator mi = m.begin(); mi != m.end(); ++mi)
2738 {
2739 std::string k = mi->first;
2740 std::string v = mi->second;
2741 data = replace_all( data, k, v );
2742 }
2743
2744 // make sure there is something in the replacement other than commas and spaces
2745 std::string tmpstring = data;
2746 tmpstring = replace_all( tmpstring, " ", "" );
2747 tmpstring = replace_all( tmpstring, ",", "" );
2748 if (tmpstring.empty()) {
2749 UT_DEBUGMSG(("stylesheet results in empty data, using name() instead\n"));
2750 data = name();
2751 }
2752
2753 UT_DEBUGMSG(("Updating with new formatting:%s\n", data.c_str() ));
2754 pDoc->insertSpan( startpos, data );
2755 pView->setPoint( startpos );
2756 }
2757
2758
~PD_RDFSemanticStylesheet()2759 PD_RDFSemanticStylesheet::~PD_RDFSemanticStylesheet()
2760 {
2761 }
2762
2763 std::string
stylesheetTypeSystem()2764 PD_RDFSemanticStylesheet::stylesheetTypeSystem()
2765 {
2766 return "System";
2767 }
2768
2769 std::string
stylesheetTypeUser()2770 PD_RDFSemanticStylesheet::stylesheetTypeUser()
2771 {
2772 return "User";
2773 }
2774
2775
2776 std::string
uuid() const2777 PD_RDFSemanticStylesheet::uuid() const
2778 {
2779 return m_uuid;
2780 }
2781
2782 std::string
name() const2783 PD_RDFSemanticStylesheet::name() const
2784 {
2785 return m_name;
2786 }
2787
2788 std::string
templateString() const2789 PD_RDFSemanticStylesheet::templateString() const
2790 {
2791 return m_templateString;
2792 }
2793
2794 std::string
type() const2795 PD_RDFSemanticStylesheet::type() const
2796 {
2797 return m_type;
2798 }
2799
2800 bool
isMutable() const2801 PD_RDFSemanticStylesheet::isMutable() const
2802 {
2803 return m_isMutable;
2804 }
2805
2806
2807 /************************************************************/
2808 /************************************************************/
2809 /************************************************************/
2810
PD_RDFSemanticItemViewSite(PD_RDFSemanticItemHandle _si,const std::string & _xmlid)2811 PD_RDFSemanticItemViewSite::PD_RDFSemanticItemViewSite( PD_RDFSemanticItemHandle _si, const std::string& _xmlid )
2812 : m_xmlid(_xmlid)
2813 , m_semItem(_si)
2814 {
2815 }
2816
PD_RDFSemanticItemViewSite(PD_RDFSemanticItemHandle _si,PT_DocPosition pos)2817 PD_RDFSemanticItemViewSite::PD_RDFSemanticItemViewSite( PD_RDFSemanticItemHandle _si, PT_DocPosition pos )
2818 : m_semItem(_si)
2819 {
2820 std::set< std::string > posxml;
2821 m_semItem->getRDF()->addRelevantIDsForPosition( posxml, pos );
2822 std::set< std::string > sixml = m_semItem->getXMLIDs();
2823 std::set< std::string > tmp;
2824 std::set_intersection( posxml.begin(), posxml.end(),
2825 sixml.begin(), sixml.end(),
2826 inserter( tmp, tmp.end() ));
2827 if( tmp.empty() )
2828 {
2829 // error
2830 }
2831 else
2832 {
2833 m_xmlid = *(tmp.begin());
2834 }
2835 }
2836
2837
2838
~PD_RDFSemanticItemViewSite()2839 PD_RDFSemanticItemViewSite::~PD_RDFSemanticItemViewSite()
2840 {
2841 }
2842
2843 PD_RDFSemanticStylesheetHandle
stylesheet() const2844 PD_RDFSemanticItemViewSite::stylesheet() const
2845 {
2846 std::string name = getProperty("stylesheet", RDF_SEMANTIC_STYLESHEET_NAME);
2847 std::string type = getProperty("stylesheet-type", PD_RDFSemanticStylesheet::stylesheetTypeSystem());
2848 std::string uuid = getProperty("stylesheet-uuid", "");
2849
2850 UT_DEBUGMSG(("stylesheet at site, format(), xmlid:%s\n", m_xmlid.c_str() ));
2851 UT_DEBUGMSG((" sheet:%s type:%s\n", name.c_str(), type.c_str() ));
2852
2853 PD_RDFSemanticStylesheetHandle ret;
2854 if (!uuid.empty())
2855 {
2856 ret = m_semItem->findStylesheetByUuid( uuid );
2857 }
2858 if (!ret)
2859 {
2860 ret = m_semItem->findStylesheetByName( type, name );
2861 }
2862 if (!ret)
2863 {
2864 // safety first, there will always be a default stylesheet
2865 ret = m_semItem->defaultStylesheet();
2866 }
2867 return ret;
2868 }
2869
2870
2871 void
disassociateStylesheet()2872 PD_RDFSemanticItemViewSite::disassociateStylesheet()
2873 {
2874 UT_DEBUGMSG(("stylesheet at site. xmlid:%s\n", m_xmlid.c_str() ));
2875 setProperty("stylesheet", "");
2876 setProperty("stylesheet-type", "");
2877 setProperty("stylesheet-uuid", "");
2878 }
2879
2880 void
applyStylesheet(FV_View * pView,PD_RDFSemanticStylesheetHandle ss)2881 PD_RDFSemanticItemViewSite::applyStylesheet( FV_View* pView,
2882 PD_RDFSemanticStylesheetHandle ss )
2883 {
2884 if( !ss )
2885 {
2886 UT_DEBUGMSG(("apply stylesheet at site. format(), xmlid:%s NO SHEET\n", m_xmlid.c_str()));
2887 return;
2888 }
2889
2890
2891 UT_DEBUGMSG(("apply stylesheet at site. format(), xmlid:%s sheet:%s\n",
2892 m_xmlid.c_str(), ss->name().c_str() ));
2893 setStylesheetWithoutReflow( ss );
2894 reflowUsingCurrentStylesheet( pView );
2895 }
2896
2897 void
setStylesheetWithoutReflow(PD_RDFSemanticStylesheetHandle ss)2898 PD_RDFSemanticItemViewSite::setStylesheetWithoutReflow( PD_RDFSemanticStylesheetHandle ss )
2899 {
2900 // Save the stylesheet property
2901 UT_DEBUGMSG(("apply stylesheet at site. format(), xmlid:%s sheet:%s\n",
2902 m_xmlid.c_str(), ss->name().c_str() ));
2903 setProperty("stylesheet", ss->name());
2904 setProperty("stylesheet-type", ss->type());
2905 setProperty("stylesheet-uuid", ss->uuid());
2906 }
2907
2908 void
reflowUsingCurrentStylesheet(FV_View * pView)2909 PD_RDFSemanticItemViewSite::reflowUsingCurrentStylesheet( FV_View* pView )
2910 {
2911 PD_RDFSemanticStylesheetHandle ss = stylesheet();
2912 ss->format( m_semItem, pView, m_xmlid );
2913 }
2914
2915 void
select(FV_View * pView)2916 PD_RDFSemanticItemViewSite::select( FV_View* pView )
2917 {
2918 std::set< std::string > xmlids;
2919 xmlids.insert( m_xmlid );
2920 m_semItem->getRDF()->selectXMLIDs( xmlids, pView );
2921 }
2922
2923 PD_URI
linkingSubject() const2924 PD_RDFSemanticItemViewSite::linkingSubject() const
2925 {
2926 PD_DocumentRDFHandle rdf = m_semItem->getRDF();
2927 PD_URI pred("http://calligra-suite.org/rdf/site/package/common#idref");
2928 PD_Literal obj(m_xmlid);
2929
2930 // try to find it if it already exists
2931 PD_URIList ul = rdf->getSubjects( pred, obj );
2932 for( PD_URIList::iterator iter = ul.begin(); iter != ul.end(); ++iter )
2933 {
2934 return *iter;
2935 }
2936
2937 PD_DocumentRDFMutationHandle m = rdf->createMutation();
2938 PD_URI ret = m->createBNode();
2939 m->add( ret, pred, obj );
2940 m->commit();
2941 return ret;
2942 }
2943
2944 std::string
getProperty(const std::string & prop,const std::string & defval) const2945 PD_RDFSemanticItemViewSite::getProperty(const std::string &prop, const std::string &defval) const
2946 {
2947 PD_DocumentRDFHandle rdf = m_semItem->getRDF();
2948 PD_URI ls = linkingSubject();
2949 std::string fqprop = "http://calligra-suite.org/rdf/site#" + prop;
2950
2951 PD_ObjectList ol = rdf->getObjects( ls, PD_URI(fqprop) );
2952 for( PD_ObjectList::iterator iter = ol.begin(); iter != ol.end(); ++iter )
2953 {
2954 return iter->toString();
2955 }
2956 return defval;
2957 }
2958
2959 void
setProperty(const std::string & prop,const std::string & v)2960 PD_RDFSemanticItemViewSite::setProperty(const std::string &prop, const std::string &v)
2961 {
2962 PD_DocumentRDFHandle rdf = m_semItem->getRDF();
2963 std::string fqprop = "http://calligra-suite.org/rdf/site#" + prop;
2964
2965 PD_URI ls = linkingSubject();
2966 PD_URI pred(fqprop);
2967
2968 PD_DocumentRDFMutationHandle m = rdf->createMutation();
2969 m->remove( ls, pred );
2970 if( !v.empty() )
2971 m->add( ls, pred, PD_Literal(v) );
2972 m->commit();
2973 }
2974
2975 void
selectRange(FV_View * pView,std::pair<PT_DocPosition,PT_DocPosition> range)2976 PD_RDFSemanticItemViewSite::selectRange( FV_View* pView, std::pair< PT_DocPosition, PT_DocPosition > range )
2977 {
2978 pView->selectRange( range );
2979 }
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998 /********************************************************************************/
2999 /********************************************************************************/
3000 /********************************************************************************/
3001 /********************************************************************************/
3002
3003
3004
PD_DocumentRDF(PD_Document * doc)3005 PD_DocumentRDF::PD_DocumentRDF( PD_Document* doc )
3006 :
3007 m_doc( doc ),
3008 m_indexAP( 0 ),
3009 m_haveSemItems( false )
3010 {
3011 UT_DEBUGMSG(("PD_DocumentRDF() this:%p doc:%p\n",this,doc));
3012 }
3013
~PD_DocumentRDF()3014 PD_DocumentRDF::~PD_DocumentRDF()
3015 {
3016 UT_DEBUGMSG(("~PD_DocumentRDF() this:%p\n", this));
3017 }
3018
3019 std::string
makeLegalXMLID(const std::string & s)3020 PD_DocumentRDF::makeLegalXMLID( const std::string& s )
3021 {
3022 std::string ret;
3023 for( std::string::const_iterator iter = s.begin(); iter != s.end(); ++iter )
3024 {
3025 char ch = *iter;
3026 if( ch >= 'a' && ch <= 'z' )
3027 ret += ch;
3028 else if( ch >= 'A' && ch <= 'Z' )
3029 ret += ch;
3030 else if( ch >= '0' && ch <= '9' )
3031 ret += ch;
3032 else
3033 ret += '_';
3034 }
3035
3036 return ret;
3037 }
3038
3039 void
relinkRDFToNewXMLID(const std::string & oldxmlid,const std::string & newxmlid,bool deepCopyRDF)3040 PD_DocumentRDF::relinkRDFToNewXMLID( const std::string& oldxmlid,
3041 const std::string& newxmlid,
3042 bool deepCopyRDF )
3043 {
3044 if( deepCopyRDF )
3045 {
3046 // FIXME: todo
3047 UT_DEBUGMSG(("relinkRDFToNewXMLID DEEP COPY FIXME oldid:%s newid:%s\n",
3048 oldxmlid.c_str(), newxmlid.c_str() ));
3049 }
3050
3051 UT_DEBUGMSG(("relinkRDFToNewXMLID oldid:%s newid:%s\n",
3052 oldxmlid.c_str(), newxmlid.c_str() ));
3053
3054 PD_DocumentRDFMutationHandle m = createMutation();
3055 PD_URI idref("http://docs.oasis-open.org/opendocument/meta/package/common#idref");
3056
3057 std::set< std::string > oldlist;
3058 oldlist.insert( oldxmlid );
3059 std::string sparql = getSPARQL_LimitedToXMLIDList( oldlist );
3060 UT_DEBUGMSG(("relinkRDFToNewXMLID sparql:%s\n", sparql.c_str() ));
3061
3062 PD_DocumentRDFHandle rdf = getDocument()->getDocumentRDF();
3063 PD_RDFQuery q( rdf, rdf );
3064 PD_ResultBindings_t bindings = q.executeQuery( sparql );
3065
3066 for( PD_ResultBindings_t::iterator iter = bindings.begin(); iter != bindings.end(); ++iter )
3067 {
3068 std::map< std::string, std::string > d = *iter;
3069
3070 PD_URI s( d["s"] );
3071 PD_URI p( d["p"] );
3072 PD_Object o( d["o"] );
3073
3074 UT_DEBUGMSG(("relinkRDFToNewXMLID oldid:%s newid:%s subj:%s\n",
3075 oldxmlid.c_str(), newxmlid.c_str(), s.toString().c_str() ));
3076
3077 m->add( s, idref, PD_Literal( newxmlid ));
3078 }
3079
3080 m->commit();
3081 }
3082
3083
3084
3085 std::string
getSPARQL_LimitedToXMLIDList(const std::set<std::string> & xmlids,const std::string & extraPreds)3086 PD_DocumentRDF::getSPARQL_LimitedToXMLIDList( const std::set< std::string >& xmlids,
3087 const std::string& extraPreds )
3088 {
3089 if( xmlids.empty() )
3090 return "";
3091
3092 std::stringstream ss;
3093 ss << "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
3094 << "prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
3095 << "prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#> \n"
3096 << "prefix geo84: <http://www.w3.org/2003/01/geo/wgs84_pos#>\n"
3097 << "\n"
3098 << "select ?s ?p ?o ?rdflink \n"
3099 << "where { \n"
3100 << " ?s ?p ?o . \n"
3101 << " ?s pkg:idref ?rdflink . \n"
3102 << " filter( ";
3103
3104 std::string joiner = "";
3105 for( std::set< std::string >::const_iterator iter = xmlids.begin();
3106 iter != xmlids.end(); ++iter )
3107 {
3108 ss << joiner << " str(?rdflink) = \"" << *iter << "\" ";
3109 joiner = " || ";
3110 }
3111 ss << " ) \n";
3112 if( !extraPreds.empty() )
3113 {
3114 ss << " . " << extraPreds << "\n";
3115 }
3116
3117 ss << "}\n";
3118
3119 std::string ret = ss.str();
3120 return ret;
3121 }
3122
3123 /**
3124 * If the document changes its m_pPieceTable it needs to call here
3125 * too.
3126 *
3127 * In various places like PD_Document::_importFile the document
3128 * creates a new piecetable and thus must notify the DocumentRDF of
3129 * this change so we can update our AttrProp indexes and the like.
3130 */
setupWithPieceTable()3131 UT_Error PD_DocumentRDF::setupWithPieceTable()
3132 {
3133 PP_AttrProp* newAP = new PP_AttrProp();
3134 PT_AttrPropIndex newAPI = 0;
3135 pt_PieceTable* pt = getPieceTable();
3136 pt_VarSet& m_varset = pt->getVarSet();
3137 bool success = m_varset.addIfUniqueAP( newAP, &newAPI );
3138 if( !success )
3139 {
3140 UT_DEBUGMSG(("PD_DocumentRDF::setupWithPieceTable() -- could not create raw RDF AttrProperties\n"));
3141 // MIQ 2010 July: addIfUniqueAP() method states false == memory error of some kind.
3142 return UT_OUTOFMEM;
3143 }
3144 m_indexAP = newAPI;
3145 UT_DEBUGMSG(("PD_DocumentRDF::setupWithPieceTable() m_indexAP:%d\n",m_indexAP));
3146 return UT_OK;
3147 }
3148
3149
3150 /**
3151 * Change the AttrProp Index that we are using to store all the RDF.
3152 * This is used by PD_DocumentRDFMutation to commit it's changes.
3153 */
3154 void
setIndexAP(PT_AttrPropIndex idx)3155 PD_DocumentRDF::setIndexAP( PT_AttrPropIndex idx )
3156 {
3157 m_indexAP = idx;
3158 }
3159
3160 /**
3161 * Get the AttrProp index where we are storing all the RDF
3162 */
3163 PT_AttrPropIndex
getIndexAP(void) const3164 PD_DocumentRDF::getIndexAP(void) const
3165 {
3166 return m_indexAP;
3167 }
3168
3169 /**
3170 * Get the AttrProp with all the RDF in it
3171 */
3172 const PP_AttrProp*
getAP(void)3173 PD_DocumentRDF::getAP(void)
3174 {
3175 PT_AttrPropIndex indexAP = getIndexAP();
3176 pt_PieceTable* pt = getPieceTable();
3177 pt_VarSet& m_varset = pt->getVarSet();
3178 const PP_AttrProp* ret = m_varset.getAP(indexAP);
3179 return ret;
3180 }
3181
setAP(PP_AttrProp * newAP)3182 UT_Error PD_DocumentRDF::setAP( PP_AttrProp* newAP )
3183 {
3184 newAP->prune();
3185 newAP->markReadOnly();
3186 pt_PieceTable* pt = getPieceTable();
3187 pt_VarSet& m_varset = pt->getVarSet();
3188
3189 PT_AttrPropIndex newAPI = 0;
3190 bool success = m_varset.addIfUniqueAP( newAP, &newAPI );
3191 // addIfUniqueAP() eats it
3192 newAP = 0;
3193
3194 if(!success)
3195 {
3196 return UT_OUTOFMEM;
3197 }
3198 setIndexAP( newAPI );
3199 return UT_OK;
3200 }
3201
isStandAlone() const3202 bool PD_DocumentRDF::isStandAlone() const
3203 {
3204 return false;
3205 }
3206
3207
3208
3209 PD_Document*
getDocument(void) const3210 PD_DocumentRDF::getDocument(void) const
3211 {
3212 return m_doc;
3213 }
3214
3215
3216 /**
3217 * Get a list of all the objects which have the given subject and predicate.
3218 *
3219 * For example:
3220 * emu has legs
3221 * emu has eyes
3222 * would give { legs, eyes }
3223 */
getObjects(const PD_URI & s,const PD_URI & p)3224 PD_ObjectList PD_DocumentRDF::getObjects( const PD_URI& s, const PD_URI& p )
3225 {
3226 PD_ObjectList ret;
3227 apGetObjects( getAP(), ret, s, p );
3228 return ret;
3229 }
3230
3231
3232 /**
3233 * Get a list of all the subjects which have the given predicate and object.
3234 *
3235 * For example:
3236 * emu has legs
3237 * emu has eyes
3238 * human has legs
3239 * when called with ( has, legs ) would give { emu, human }
3240 */
getSubjects(const PD_URI & p,const PD_Object & o)3241 PD_URIList PD_DocumentRDF::getSubjects( const PD_URI& p, const PD_Object& o )
3242 {
3243 PD_URIList ret;
3244 apGetSubjects( getAP(), ret, p, o );
3245 return ret;
3246 }
3247
3248
3249 PD_URIList
getAllSubjects()3250 PD_DocumentRDF::getAllSubjects()
3251 {
3252 PD_URIList ret;
3253 apGetAllSubjects( getAP(), ret );
3254 return ret;
3255 }
3256
3257 /**
3258 * Internal method: Using the supplied AP, insert into ret a list of
3259 * every subject in the model. If you want to get all triples, then
3260 * first get all subjects and then use getArcsOut() to get the
3261 * predicate-object combinations for each of the subjects.
3262 */
3263
3264 PD_URIList&
apGetAllSubjects(const PP_AttrProp * AP,PD_URIList & ret)3265 PD_DocumentRDF::apGetAllSubjects( const PP_AttrProp* AP, PD_URIList& ret )
3266 {
3267 size_t count = AP->getPropertyCount();
3268 for( size_t i = 0; i<count; ++i )
3269 {
3270 const gchar * szName = 0;
3271 const gchar * szValue = 0;
3272 if( AP->getNthProperty( i, szName, szValue) )
3273 {
3274 std::string subj = szName;
3275 ret.push_back(subj);
3276 }
3277 }
3278 return ret;
3279 }
3280
3281
3282
3283 /**
3284 * Get the predicate and objects which have the given subject.
3285 * This can be thought of as all the arcs from the node at 's' in the RDF
3286 * graph.
3287 */
3288 POCol
getArcsOut(const PD_URI & s)3289 PD_DocumentRDF::getArcsOut( const PD_URI& s )
3290 {
3291 POCol ret;
3292 apGetArcsOut( getAP(), ret, s );
3293 return ret;
3294 }
3295
3296 /**
3297 * Get the predicate and objects which have the given subject.
3298 * This can be thought of as all the arcs from the node at 's' in the RDF
3299 * graph.
3300 */
3301 POCol&
apGetArcsOut(const PP_AttrProp * AP,POCol & ret,const PD_URI & s)3302 PD_DocumentRDF::apGetArcsOut( const PP_AttrProp* AP, POCol& ret, const PD_URI& s )
3303 {
3304 const gchar* szValue = 0;
3305 if( AP->getProperty( s.toString().c_str(), szValue) )
3306 {
3307 ret = decodePOCol(szValue);
3308 }
3309 return ret;
3310 }
3311
3312
3313 /**
3314 * Internal method: Using the supplied AP, insert into ret a list of
3315 * all the objects which have the given subject and predicate.
3316 *
3317 * For example:
3318 * emu has legs
3319 * emu has eyes
3320 * would give { legs, eyes }
3321 */
3322 PD_ObjectList&
apGetObjects(const PP_AttrProp * AP,PD_ObjectList & ret,const PD_URI & s,const PD_URI & p)3323 PD_DocumentRDF::apGetObjects( const PP_AttrProp* AP, PD_ObjectList& ret, const PD_URI& s, const PD_URI& p )
3324 {
3325 const gchar* szValue = 0;
3326 if( AP->getProperty( s.toString().c_str(), szValue) )
3327 {
3328 POCol l = decodePOCol(szValue);
3329 std::pair< POCol::iterator, POCol::iterator > range
3330 = std::equal_range( l.begin(), l.end(), p );
3331 for( POCol::iterator iter = range.first; iter != range.second; ++iter )
3332 {
3333 ret.push_back( iter->second );
3334 }
3335 }
3336 return ret;
3337 }
3338
3339 /**
3340 * Internal method: Using the supplied AP, insert into ret a list of
3341 * all the subjects which have the given predicate and object.
3342 *
3343 * For example:
3344 * emu has legs
3345 * emu has eyes
3346 * human has legs
3347 * when called with ( has, legs ) would give { emu, human }
3348 */
3349 PD_URIList&
apGetSubjects(const PP_AttrProp * AP,PD_URIList & ret,const PD_URI & p,const PD_Object & o)3350 PD_DocumentRDF::apGetSubjects( const PP_AttrProp* AP, PD_URIList& ret, const PD_URI& p, const PD_Object& o )
3351 {
3352 size_t count = AP->getPropertyCount();
3353 for( size_t i = 0; i<count; ++i )
3354 {
3355 const gchar * szName = 0;
3356 const gchar * szValue = 0;
3357 if( AP->getNthProperty( i, szName, szValue) )
3358 {
3359 POCol l = decodePOCol( szValue );
3360 std::string subj = szName;
3361 for( POCol::iterator iter = l.begin(); iter!=l.end(); ++iter )
3362 {
3363 if( iter->first == p && iter->second == o )
3364 ret.push_back(subj);
3365 }
3366 }
3367 }
3368 return ret;
3369 }
3370
3371
3372
3373 /**
3374 * Internal method: tests if the AP has the triple or not.
3375 */
apContains(const PP_AttrProp * AP,const PD_URI & s,const PD_URI & p,const PD_Object & o)3376 bool PD_DocumentRDF::apContains( const PP_AttrProp* AP, const PD_URI& s, const PD_URI& p, const PD_Object& o )
3377 {
3378 const gchar* szValue = 0;
3379 if( AP->getProperty( s.toString().c_str(), szValue) )
3380 {
3381 POCol l = decodePOCol(szValue);
3382
3383 std::pair< POCol::iterator, POCol::iterator > range
3384 = std::equal_range( l.begin(), l.end(), p );
3385 for( POCol::iterator iter = range.first; iter != range.second; ++iter )
3386 {
3387 if( iter->second == o )
3388 return true;
3389 }
3390 }
3391 return false;
3392 }
3393
3394 /**
3395 * Test if the given triple is in the RDF or not.
3396 */
3397 bool
contains(const PD_URI & s,const PD_URI & p,const PD_Object & o)3398 PD_DocumentRDF::contains( const PD_URI& s, const PD_URI& p, const PD_Object& o )
3399 {
3400 return apContains( getAP(), s, p, o );
3401 }
3402 bool
contains(const PD_RDFStatement & st)3403 PD_DocumentRDF::contains( const PD_RDFStatement& st )
3404 {
3405 return contains( st.getSubject(), st.getPredicate(), st.getObject() );
3406 }
3407
3408
3409 /**
3410 * Get the total number of triples in the model. This can be
3411 * relatively expensive to calculate. So definately don't keep
3412 * on doing it in a loop.
3413 */
3414 long
getTripleCount()3415 PD_DocumentRDF::getTripleCount()
3416 {
3417 long ret = 0;
3418
3419 PD_URIList subjects = getAllSubjects();
3420 PD_URIList::iterator subjend = subjects.end();
3421 for( PD_URIList::iterator subjiter = subjects.begin();
3422 subjiter != subjend; ++subjiter )
3423 {
3424 PD_URI subject = *subjiter;
3425 POCol polist = getArcsOut( subject );
3426 POCol::iterator poend = polist.end();
3427 for( POCol::iterator poiter = polist.begin();
3428 poiter != poend; ++poiter )
3429 {
3430 PD_URI predicate = poiter->first;
3431 PD_Object object = poiter->second;
3432 ++ret;
3433 }
3434 }
3435 return ret;
3436 }
3437
3438
3439 PD_RDFModelIterator
begin()3440 PD_DocumentRDF::begin()
3441 {
3442 // UT_DEBUGMSG(("docrdf::begin() ap:%p\n", getAP() ));
3443
3444 PD_RDFModelHandle model = getDocument()->getDocumentRDF();
3445 PD_RDFModelIterator iter( model, getAP() );
3446 return iter;
3447 }
3448
3449 PD_RDFModelIterator
end()3450 PD_DocumentRDF::end()
3451 {
3452 return PD_RDFModelIterator();
3453 }
3454
3455
3456
3457 /**
3458 * The single way that you can update the document RDF is through
3459 * an PD_DocumentRDFMutation. This is where you get one of those.
3460 *
3461 * @see PD_DocumentRDFMutation
3462 */
3463 PD_DocumentRDFMutationHandle
createMutation()3464 PD_DocumentRDF::createMutation()
3465 {
3466 PD_DocumentRDFMutationHandle h(new PD_DocumentRDFMutation(this));
3467 return h;
3468 }
3469
3470 /**
3471 * Internal method: used by AbiCollab to update the RDF
3472 */
3473 void
handleCollabEvent(gchar ** szAtts,gchar ** szProps)3474 PD_DocumentRDF::handleCollabEvent( gchar** szAtts, gchar** szProps )
3475 {
3476 PD_DocumentRDFMutationHandle h = createMutation();
3477 h->handleCollabEvent( szAtts, szProps );
3478 h->commit();
3479 }
3480
3481
3482 pt_PieceTable *
getPieceTable(void) const3483 PD_DocumentRDF::getPieceTable(void) const
3484 {
3485 return m_doc->getPieceTable();
3486 }
3487
3488
3489
3490 //////////////////////////////////
3491 //////////////////////////////////
3492 //////////////////////////////////
3493
3494 void
setup(const PP_AttrProp * pAP)3495 RDFAnchor::setup( const PP_AttrProp* pAP )
3496 {
3497 const gchar * v = 0;
3498 // if(pAP->getAttribute("this-is-an-rdf-anchor", v) && v)
3499 // UT_DEBUGMSG(("RDFAnchor() is-rdf-a:%s\n",v));
3500 // if(pAP->getAttribute(PT_RDF_END, v) && v)
3501 // UT_DEBUGMSG(("RDFAnchor() PT_RDF_END:%s\n",v));
3502
3503 if( pAP->getAttribute(PT_RDF_END, v) && v)
3504 {
3505 m_isEnd = !strcmp(v,"yes");
3506 }
3507 if( pAP->getAttribute(PT_XMLID, v) && v)
3508 {
3509 m_xmlid = v;
3510 }
3511 }
3512
RDFAnchor(PD_Document * pDoc,PT_AttrPropIndex api)3513 RDFAnchor::RDFAnchor( PD_Document* pDoc, PT_AttrPropIndex api )
3514 :
3515 m_isEnd( false )
3516 {
3517 const PP_AttrProp * pAP = NULL;
3518 pDoc->getAttrProp( api, &pAP );
3519 setup( pAP );
3520 }
3521
3522
RDFAnchor(PD_Document * doc,pf_Frag * pf)3523 RDFAnchor::RDFAnchor( PD_Document* doc, pf_Frag* pf )
3524 :
3525 m_isEnd( false )
3526 {
3527 PT_AttrPropIndex api = pf->getIndexAP();
3528 const PP_AttrProp * pAP = NULL;
3529 doc->getAttrProp( api, &pAP );
3530 setup( pAP );
3531 }
3532
3533
RDFAnchor(const PP_AttrProp * pAP)3534 RDFAnchor::RDFAnchor( const PP_AttrProp* pAP )
3535 :
3536 m_isEnd( false )
3537 {
3538 setup( pAP );
3539 }
3540
isEnd()3541 bool RDFAnchor::isEnd()
3542 {
3543 return m_isEnd;
3544 }
getID()3545 std::string RDFAnchor::getID()
3546 {
3547 return m_xmlid;
3548 }
3549
3550 //////////////////////////////////
3551 //////////////////////////////////
3552 //////////////////////////////////
3553
3554 std::set< std::string >&
getAllIDs(std::set<std::string> & ret)3555 PD_DocumentRDF::getAllIDs( std::set< std::string >& ret )
3556 {
3557 PD_Document* doc = getDocument();
3558 pf_Frag * iter = doc->getFragFromPosition(0);
3559 // pf_Frag* last = doc->getLastFrag();
3560
3561 UT_DEBUGMSG(( "getAllIDs() iter starting at:%p\n", iter ));
3562
3563 for( ; iter; iter = iter->getNext() )
3564 {
3565 pf_Frag* pf = iter;
3566 std::string xmlid = pf->getXMLID();
3567 if( !xmlid.empty() )
3568 ret.insert( xmlid );
3569 }
3570
3571 return ret;
3572 }
3573
3574
3575 std::pair< PT_DocPosition, PT_DocPosition >
getIDRange(const std::string & xmlid) const3576 PD_DocumentRDF::getIDRange( const std::string& xmlid ) const
3577 {
3578 std::pair< PT_DocPosition, PT_DocPosition > ret( 0, 0 );
3579 PD_Document* doc = getDocument();
3580 pf_Frag * iter = doc->getFragFromPosition(0);
3581
3582 // UT_DEBUGMSG(( "getIDRange() iter starting at:%p\n", iter ));
3583
3584 for( ; iter; iter = iter->getNext() )
3585 {
3586 pf_Frag* pf = iter;
3587 std::string x = pf->getXMLID();
3588 if( xmlid == x )
3589 {
3590 PT_DocPosition epos = pf->getPos() + pf->getLength();
3591 pf_Frag* e = pf->getNext();
3592 for( ; e; e = e->getNext() )
3593 {
3594 if( e->getType() == pf_Frag::PFT_Strux )
3595 {
3596 const pf_Frag_Strux* pfs = static_cast<const pf_Frag_Strux*>(e);
3597 PTStruxType st = pfs->getStruxType();
3598 if( st == PTX_Block || st == PTX_SectionCell )
3599 {
3600 epos = e->getPos() - 1;
3601 break;
3602 }
3603 }
3604 if( e->getType() == pf_Frag::PFT_Object )
3605 {
3606 const pf_Frag_Object* pfo = static_cast<const pf_Frag_Object*>(e);
3607 if( pfo->getObjectType() == PTO_RDFAnchor )
3608 {
3609 RDFAnchor a( doc, e );
3610 if( a.getID() == xmlid )
3611 {
3612 epos = e->getPos();
3613 break;
3614 }
3615 }
3616 }
3617
3618 }
3619 return std::make_pair( pf->getPos(), epos );
3620 }
3621 }
3622
3623 return ret;
3624 }
3625
3626
3627 std::set< std::string >&
addRelevantIDsForRange(std::set<std::string> & ret,PD_DocumentRange * range)3628 PD_DocumentRDF::addRelevantIDsForRange( std::set< std::string >& ret,
3629 PD_DocumentRange* range )
3630 {
3631 addRelevantIDsForRange( ret, std::make_pair( range->m_pos1, range->m_pos2 ));
3632 return ret;
3633 }
3634
3635 std::list< pf_Frag_Object* >
getObjectsInScopeOfTypesForRange(std::set<PTObjectType> objectTypes,std::pair<PT_DocPosition,PT_DocPosition> range)3636 PD_DocumentRDF::getObjectsInScopeOfTypesForRange( std::set< PTObjectType > objectTypes,
3637 std::pair< PT_DocPosition, PT_DocPosition > range )
3638 {
3639 std::list< pf_Frag_Object* > ret;
3640 // PD_Document* doc = getDocument();
3641 pt_PieceTable* pt = getPieceTable();
3642 PT_DocPosition start = range.first;
3643 PT_DocPosition curr = range.second;
3644 PT_DocPosition searchBackThisFar = 0;
3645 if( !curr )
3646 curr = start;
3647
3648 //
3649 // Allow recursion of text:meta where an outside tag might encase the point but
3650 // another text:meta might completely be before point. Consider:
3651 //
3652 // <text:meta xml:id="outside"> ....
3653 // ... <text:meta xml:id="nested">boo</text:meta>
3654 // ... POINT ...
3655 // </text:meta>
3656 //
3657 // In this case, we want to ignore the xml:id == nested anchors but find the
3658 // xml:id == outside one
3659 //
3660 std::set< std::string > m_ignoreIDSet;
3661
3662 //
3663 // FIXME: Some form of index would be nice, rather than walking back the entire
3664 // document to find the RDF Anchors.
3665 //
3666 for( ; curr > searchBackThisFar; )
3667 {
3668 pf_Frag* pf = 0;
3669 PT_BlockOffset boffset;
3670
3671 if( pt->getFragFromPosition( curr, &pf, &boffset ) )
3672 {
3673 xxx_UT_DEBUGMSG(("PD_DocumentRDF::getObjectsInScope() current:%d frag type:%d len:%d \n",
3674 curr, pf->getType(), pf->getLength() ));
3675
3676 // skip backwards fast if possible.
3677 if(pf->getType() != pf_Frag::PFT_Object)
3678 {
3679 xxx_UT_DEBUGMSG(("PD_DocumentRDF::getObjectsInScope() SKIPPING BACK!\n" ));
3680 curr = pf->getPos() - 1;
3681 continue;
3682 }
3683 // otherwise keep moving backwards slowly anyway
3684 --curr;
3685
3686
3687 // check what RDF is attached to this object.
3688 if(pf->getType() == pf_Frag::PFT_Object)
3689 {
3690 pf_Frag_Object* pOb = static_cast<pf_Frag_Object*>(pf);
3691 const PP_AttrProp * pAP = NULL;
3692
3693 xxx_UT_DEBUGMSG(("PD_DocumentRDF::getObjectsInScope() po type:%d\n",
3694 pOb->getObjectType() ));
3695
3696 if( pOb->getObjectType() == PTO_Bookmark
3697 && objectTypes.count(pOb->getObjectType()))
3698 {
3699 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3700 const char* v = 0;
3701 if( pAP->getAttribute(PT_XMLID, v) && v)
3702 {
3703 std::string xmlid = v;
3704 bool isEnd = pAP->getAttribute("type", v) && v && !strcmp(v,"end");
3705
3706 xxx_UT_DEBUGMSG(("PD_DocumentRDF::getObjectsInScope() isEnd:%d id:%s\n",
3707 isEnd, xmlid.c_str() ));
3708
3709 if( isEnd && curr < start )
3710 {
3711 m_ignoreIDSet.insert( xmlid );
3712 }
3713 else
3714 {
3715 if( !m_ignoreIDSet.count( xmlid ))
3716 ret.push_back( pOb );
3717 }
3718 }
3719 }
3720
3721 if( pOb->getObjectType() == PTO_RDFAnchor
3722 && objectTypes.count(pOb->getObjectType()))
3723 {
3724 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3725
3726 RDFAnchor a(pAP);
3727 xxx_UT_DEBUGMSG(("PD_DocumentRDF::getObjectsInScope() isEnd:%d id:%s\n",
3728 a.isEnd(), a.getID().c_str() ));
3729
3730 if( a.isEnd() && curr < start )
3731 {
3732 m_ignoreIDSet.insert( a.getID() );
3733 }
3734 else
3735 {
3736 if( !m_ignoreIDSet.count( a.getID() ))
3737 ret.push_back( pOb );
3738 }
3739 }
3740 }
3741 }
3742 }
3743
3744 return ret;
3745 }
3746
3747
3748 std::set< std::string >&
addXMLIDsForObjects(std::set<std::string> & ret,std::list<pf_Frag_Object * > objectList)3749 PD_DocumentRDF::addXMLIDsForObjects( std::set< std::string >& ret, std::list< pf_Frag_Object* > objectList )
3750 {
3751 const PP_AttrProp * pAP = NULL;
3752
3753 for( std::list< pf_Frag_Object* >::iterator iter = objectList.begin();
3754 iter != objectList.end(); ++iter )
3755 {
3756 pf_Frag_Object* pOb = *iter;
3757
3758 if( pOb->getObjectType() == PTO_Bookmark )
3759 {
3760 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3761 const char* v = 0;
3762 if( pAP->getAttribute(PT_XMLID, v) && v)
3763 {
3764 std::string xmlid = v;
3765 ret.insert( xmlid );
3766 }
3767 }
3768
3769 if( pOb->getObjectType() == PTO_RDFAnchor )
3770 {
3771 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3772 RDFAnchor a(pAP);
3773 ret.insert( a.getID() );
3774 xxx_UT_DEBUGMSG(("addXMLIDsForObjects() xmlid:%s\n", a.getID().c_str() ));
3775 }
3776 }
3777 return ret;
3778 }
3779
3780 PT_DocPosition
addXMLIDsForBlockAndTableCellForPosition(std::set<std::string> & col,PT_DocPosition pos)3781 PD_DocumentRDF::addXMLIDsForBlockAndTableCellForPosition( std::set< std::string >& col, PT_DocPosition pos )
3782 {
3783 PT_DocPosition ret = pos;
3784 PD_Document* doc = getDocument();
3785 pt_PieceTable* pt = getPieceTable();
3786
3787 pf_Frag* frag = doc->getFragFromPosition( pos );
3788 ret = frag->getPos() - 1;
3789
3790 //
3791 // xml:id attached to containing paragraph/header
3792 // <text:p> / <text:h>
3793 //
3794 pf_Frag_Strux* psdh;
3795 if( pt->getStruxOfTypeFromPosition( pos, PTX_Block, &psdh ) && psdh )
3796 {
3797 xxx_UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() block pos:%d\n", pos ));
3798 PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
3799 const PP_AttrProp * AP = NULL;
3800 doc->getAttrProp(api,&AP);
3801 if( AP )
3802 {
3803 const char * v = NULL;
3804 if(AP->getAttribute("xml:id", v))
3805 {
3806 xxx_UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() xmlid:%s \n",v));
3807 col.insert(v);
3808 }
3809 }
3810 }
3811
3812 //
3813 // xml:id attached to containing table:table-cell
3814 //
3815 if( pt->getStruxOfTypeFromPosition( pos, PTX_SectionCell, &psdh ) && psdh )
3816 {
3817 xxx_UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() cell pos:%d\n", pos ));
3818 PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
3819 const PP_AttrProp * AP = NULL;
3820 doc->getAttrProp(api,&AP);
3821 if( AP )
3822 {
3823 const char * v = NULL;
3824 if(AP->getAttribute("xml:id", v))
3825 {
3826 xxx_UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() xmlid:%s \n",v));
3827 col.insert(v);
3828 #if 0
3829 if(AP->getAttribute("props", v)) {
3830 xxx_UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() props:%s \n",v));
3831 }
3832 #endif
3833 }
3834 }
3835 }
3836
3837 return ret;
3838 }
3839
3840
3841 std::set< std::string >&
addRelevantIDsForRange(std::set<std::string> & ret,std::pair<PT_DocPosition,PT_DocPosition> range)3842 PD_DocumentRDF::addRelevantIDsForRange( std::set< std::string >& ret,
3843 std::pair< PT_DocPosition, PT_DocPosition > range )
3844 {
3845 //
3846 // A sneaky optimization, for the first position we might have to
3847 // search backward to the start of the document to see opening
3848 // blocks and text:meta elements which might have RDF attached.
3849 // However, for startpos+1 to the end position we only have to
3850 // consider the range itself because we have already added any IDs
3851 // which might have opened before the range with the first
3852 // backward search.
3853 //
3854 PT_DocPosition pos = range.first;
3855
3856 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() xxxyyy begin:%d end:%d\n", range.first, range.second ));
3857 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() xxxyyy looking back to find bookmark and rdf anchor openings...\n" ));
3858 std::set< PTObjectType > objectTypes;
3859 objectTypes.insert( PTO_Bookmark );
3860 objectTypes.insert( PTO_RDFAnchor );
3861 std::list< pf_Frag_Object* > objectList = getObjectsInScopeOfTypesForRange( objectTypes, range );
3862 addXMLIDsForObjects( ret, objectList );
3863 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() xxxyyy objectList.sz:%ld\n", objectList.size() ));
3864 addXMLIDsForBlockAndTableCellForPosition( ret, pos );
3865
3866
3867 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() xxxyyy inspecting range...\n" ));
3868 // PT_DocPosition searchBackThisFar = pos;
3869 ++pos;
3870
3871 PT_DocPosition endPos = range.second;
3872 if( !endPos ) {
3873 endPos = range.first+1;
3874 }
3875
3876 for( PT_DocPosition curr = endPos; curr >= range.first; )
3877 {
3878 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() xxxyyy looping curr:%d\n", curr ));
3879 curr = addXMLIDsForBlockAndTableCellForPosition( ret, curr );
3880 }
3881
3882
3883
3884 // priv_addRelevantIDsForPosition( ret, endPos, searchBackThisFar );
3885
3886 // for( ; pos <= range.second; ++pos )
3887 // {
3888 // priv_addRelevantIDsForPosition( ret, pos, searchBackThisFar );
3889 // }
3890 xxx_UT_DEBUGMSG(("PD_DocumentRDF::addRelevantIDsForRange() ret begin:%d end:%d\n", range.first, range.second ));
3891 return ret;
3892 }
3893
3894 std::set< std::string >&
addRelevantIDsForPosition(std::set<std::string> & ret,PT_DocPosition pos)3895 PD_DocumentRDF::addRelevantIDsForPosition( std::set< std::string >& ret,
3896 PT_DocPosition pos )
3897 {
3898 addRelevantIDsForRange( ret, std::make_pair( pos, (PT_DocPosition)0 ) );
3899 return ret;
3900 }
3901
3902 std::set< std::string >&
priv_addRelevantIDsForPosition(std::set<std::string> & ret,PT_DocPosition pos,PT_DocPosition searchBackThisFar)3903 PD_DocumentRDF::priv_addRelevantIDsForPosition( std::set< std::string >& ret,
3904 PT_DocPosition pos,
3905 PT_DocPosition searchBackThisFar )
3906 {
3907 PD_Document* doc = getDocument();
3908 pt_PieceTable* pt = getPieceTable();
3909 PT_DocPosition curr = pos;
3910
3911 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() current:%d searchBackLimit:%d\n",
3912 curr, searchBackThisFar ));
3913
3914 //
3915 // Allow recursion of text:meta where an outside tag might encase the point but
3916 // another text:meta might completely be before point. Consider:
3917 //
3918 // <text:meta xml:id="outside"> ....
3919 // ... <text:meta xml:id="nested">boo</text:meta>
3920 // ... POINT ...
3921 // </text:meta>
3922 //
3923 // In this case, we want to ignore the xml:id == nested anchors but find the
3924 // xml:id == outside one
3925 //
3926 std::set< std::string > m_ignoreIDSet;
3927
3928 //
3929 // FIXME: Some form of index would be nice, rather than walking back the entire
3930 // document to find the RDF Anchors.
3931 //
3932 for( ; curr > searchBackThisFar; )
3933 {
3934 pf_Frag* pf = 0;
3935 PT_BlockOffset boffset;
3936
3937 if( pt->getFragFromPosition( curr, &pf, &boffset ) )
3938 {
3939 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() current:%d frag type:%d len:%d \n",
3940 curr, pf->getType(), pf->getLength() ));
3941
3942 // skip backwards fast if possible.
3943 if(pf->getType() != pf_Frag::PFT_Object)
3944 {
3945 curr = pf->getPos() - 1;
3946 continue;
3947 }
3948 // otherwise keep moving backwards slowly anyway
3949 --curr;
3950
3951
3952 // check what RDF is attached to this object.
3953 if(pf->getType() == pf_Frag::PFT_Object)
3954 {
3955 pf_Frag_Object* pOb = static_cast<pf_Frag_Object*>(pf);
3956 const PP_AttrProp * pAP = NULL;
3957
3958 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() po type:%d\n",
3959 pOb->getObjectType() ));
3960
3961 if(pOb->getObjectType() == PTO_Bookmark)
3962 {
3963 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3964 const char* v = 0;
3965 if( pAP->getAttribute(PT_XMLID, v) && v)
3966 {
3967 std::string xmlid = v;
3968 bool isEnd = pAP->getAttribute("type", v) && v && !strcmp(v,"end");
3969
3970 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() isEnd:%d id:%s\n",
3971 isEnd, xmlid.c_str() ));
3972
3973 if( isEnd )
3974 {
3975 m_ignoreIDSet.insert( xmlid );
3976 }
3977 else
3978 {
3979 if( !m_ignoreIDSet.count( xmlid ))
3980 ret.insert( xmlid );
3981 }
3982 }
3983 }
3984
3985 if(pOb->getObjectType() == PTO_RDFAnchor)
3986 {
3987 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
3988
3989 RDFAnchor a(pAP);
3990 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() isEnd:%d id:%s\n",
3991 a.isEnd(), a.getID().c_str() ));
3992
3993 if( a.isEnd() )
3994 {
3995 m_ignoreIDSet.insert( a.getID() );
3996 }
3997 else
3998 {
3999 if( !m_ignoreIDSet.count( a.getID() ))
4000 ret.insert( a.getID() );
4001 }
4002 }
4003 }
4004 }
4005 }
4006
4007
4008 //
4009 // xml:id attached to containing paragraph/header
4010 // <text:p> / <text:h>
4011 //
4012 pf_Frag_Strux* psdh;
4013 if( pt->getStruxOfTypeFromPosition( pos, PTX_Block, &psdh ) && psdh )
4014 {
4015 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() block pos:%d\n", pos ));
4016 PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
4017 const PP_AttrProp * AP = NULL;
4018 doc->getAttrProp(api,&AP);
4019 if( AP )
4020 {
4021 const char * v = NULL;
4022 if(AP->getAttribute("xml:id", v))
4023 {
4024 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() xmlid:%s \n",v));
4025 ret.insert(v);
4026 }
4027 }
4028 }
4029
4030 //
4031 // xml:id attached to containing table:table-cell
4032 //
4033 if( pt->getStruxOfTypeFromPosition( pos, PTX_SectionCell, &psdh ) && psdh )
4034 {
4035 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() cell pos:%d\n", pos ));
4036 PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
4037 const PP_AttrProp * AP = NULL;
4038 doc->getAttrProp(api,&AP);
4039 if( AP )
4040 {
4041 const char * v = NULL;
4042 if(AP->getAttribute("xml:id", v))
4043 {
4044 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() xmlid:%s \n",v));
4045 ret.insert(v);
4046
4047 if(AP->getAttribute("props", v)) {
4048 UT_DEBUGMSG(("PD_DocumentRDF::priv_addRelevantIDsForPosition() props:%s \n",v));
4049 }
4050
4051 }
4052 }
4053 }
4054
4055 return ret;
4056 }
4057
4058
4059
4060 PD_RDFModelHandle
createScratchModel()4061 PD_DocumentRDF::createScratchModel()
4062 {
4063 PD_Document* doc = getDocument();
4064 PP_AttrProp* AP = new PP_AttrProp();
4065 PD_RDFModelFromAP* retModel = new PD_RDFModelFromAP( doc, AP );
4066 PD_RDFModelHandle ret( retModel );
4067 return ret;
4068 }
4069
4070 PD_URI
getManifestURI()4071 PD_DocumentRDF::getManifestURI()
4072 {
4073 return PD_URI("http://abiword.org/manifest.rdf");
4074 }
4075
4076
4077
getRDFAtPosition(PT_DocPosition pos)4078 PD_RDFModelHandle PD_DocumentRDF::getRDFAtPosition( PT_DocPosition pos )
4079 {
4080 UT_DEBUG_ONLY_ARG(pos);
4081
4082 PD_Document* doc = getDocument();
4083
4084 #ifdef DEBUG
4085 std::set< std::string > IDList;
4086 addRelevantIDsForPosition( IDList, pos );
4087
4088 PP_AttrProp* AP = new PP_AttrProp();
4089 PD_RDFModelFromAP* retModel = new PD_RDFModelFromAP( doc, AP );
4090 PD_RDFModelHandle ret( retModel );
4091
4092 if( !IDList.empty() )
4093 {
4094 PD_DocumentRDFMutationHandle m = retModel->createMutation();
4095 for( std::set< std::string >::iterator iter = IDList.begin();
4096 iter != IDList.end(); ++iter )
4097 {
4098 std::string xmlid = *iter;
4099 addRDFForID( xmlid, m );
4100 }
4101 m->commit();
4102 }
4103
4104
4105 // retModel->dumpModel("RDF result for xmlid");
4106 return ret;
4107
4108
4109 // if( pt->getStruxOfTypeFromPosition( pos, PTX_Block, &psdh ) && psdh )
4110 // {
4111 // UT_DEBUGMSG(("PD_DocumentRDF::getRDFAtPosition() pos:%d\n", pos ));
4112 // PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
4113 // const PP_AttrProp * AP = NULL;
4114 // doc->getAttrProp(api,&AP);
4115 // if( AP )
4116 // {
4117 // const char * v = NULL;
4118 // if(AP->getAttribute("xml:id", v))
4119 // {
4120 // UT_DEBUGMSG(("PD_DocumentRDF::getRDFAtPosition() xmlid:%s \n",v));
4121 // PD_RDFModelHandle ret = getRDFForID( v );
4122 // return ret;
4123 // }
4124 // }
4125 // }
4126
4127 #else
4128 {
4129 // return an empty model
4130 PD_RDFModelHandle x( new PD_RDFModelFromAP( doc, new PP_AttrProp() ));
4131 return x;
4132 }
4133 #endif
4134 }
4135
addRDFForID(const std::string & xmlid,PD_DocumentRDFMutationHandle & m)4136 void PD_DocumentRDF::addRDFForID( const std::string& xmlid, PD_DocumentRDFMutationHandle& m )
4137 {
4138 // Execute query to find all triples related to xmlid
4139 // and add them all to the mutation m
4140 //
4141 // prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
4142 // prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#>
4143 // select ?s ?p ?o
4144 // where {
4145 // ?s pkg:idref ?xmlid .
4146 // ?s ?p ?o .
4147 // filter( str(?xmlid) = \"" << xmlid << "\" )
4148 // };
4149
4150 PD_URI pkg_idref("http://docs.oasis-open.org/opendocument/meta/package/common#idref");
4151 PD_Object xmlidNode( xmlid );
4152
4153 PD_URIList subjects = getAllSubjects();
4154 PD_URIList::iterator subjend = subjects.end();
4155 for( PD_URIList::iterator subjiter = subjects.begin();
4156 subjiter != subjend; ++subjiter )
4157 {
4158 bool addSubject = false;
4159
4160 PD_URI subject = *subjiter;
4161 {
4162 POCol polist = getArcsOut( subject );
4163 POCol::iterator poend = polist.end();
4164 for( POCol::iterator poiter = polist.begin();
4165 poiter != poend; ++poiter )
4166 {
4167 PD_URI predicate = poiter->first;
4168 PD_Object object = poiter->second;
4169 if( predicate == pkg_idref && object == xmlidNode )
4170 {
4171 addSubject = true;
4172 break;
4173 }
4174 }
4175 }
4176
4177
4178 if( addSubject )
4179 {
4180 POCol polist = getArcsOut( subject );
4181 POCol::iterator poend = polist.end();
4182 for( POCol::iterator poiter = polist.begin();
4183 poiter != poend; ++poiter )
4184 {
4185 PD_URI predicate = poiter->first;
4186 PD_Object object = poiter->second;
4187
4188 UT_DEBUGMSG(("PD_DocumentRDF::adding s:%s p:%s o:%s\n",
4189 subject.toString().c_str(),
4190 predicate.toString().c_str(),
4191 object.toString().c_str() ));
4192
4193 m->add( subject, predicate, object );
4194 }
4195 }
4196 }
4197 }
4198
4199
getRDFForID(const std::string & xmlid)4200 PD_RDFModelHandle PD_DocumentRDF::getRDFForID( const std::string& xmlid )
4201 {
4202 PP_AttrProp* AP = new PP_AttrProp();
4203 PD_RDFModelFromAP* retModel = new PD_RDFModelFromAP( m_doc, AP );
4204 PD_RDFModelHandle ret( retModel );
4205
4206 PD_DocumentRDFMutationHandle m = retModel->createMutation();
4207 addRDFForID( xmlid, m );
4208 m->commit();
4209
4210 // retModel->dumpModel("RDF result for xmlid");
4211 return ret;
4212 }
4213
4214
4215
4216
4217
4218
4219
4220
runMilestone2Test()4221 void PD_DocumentRDF::runMilestone2Test()
4222 {
4223 #ifdef DEBUG
4224 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() doc:%p\n", m_doc));
4225
4226 {
4227 PD_DocumentRDFMutationHandle m = createMutation();
4228 m->add( PD_URI("http://www.example.com/foo"),
4229 PD_URI("http://www.example.com/bar"),
4230 PD_Literal("AABBCC") );
4231 m->add( PD_URI("http://www.example.com/koala"),
4232 PD_URI("http://www.example.com/is-a"),
4233 PD_Literal("dangeroo",
4234 "http://www.w3.org/2001/XMLSchema#boolean" ));
4235
4236 }
4237 dumpModel();
4238
4239 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() -------------------------------\n"));
4240 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() adding some more triples\n"));
4241 {
4242 PD_DocumentRDFMutationHandle m = createMutation();
4243 m->add( PD_URI("http://www.example.com/foo"),
4244 PD_URI("http://www.example.com/bar2"),
4245 PD_Literal("extra data") );
4246 m->add( PD_URI("http://www.example.com/foo"),
4247 PD_URI("http://www.example.com/magic"),
4248 PD_Literal("card trick",
4249 "http://www.w3.org/2001/XMLSchema#string" ));
4250 m->add( PD_URI("http://www.example.com/emu"),
4251 PD_URI("http://www.example.com/lives-in"),
4252 PD_Object("http://www.example.com/australia"));
4253 m->add( PD_URI("http://www.example.com/water dragon"),
4254 PD_URI("http://www.example.com/lives-in"),
4255 PD_Object("http://www.example.com/australia"));
4256 }
4257 dumpModel();
4258
4259
4260 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() -------------------------------\n"));
4261 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() removing some triples\n"));
4262 {
4263 // This test removes something from foo, which has multiple
4264 // values in it's PO list. Also the koala is removed, so the
4265 // whole s->po mapping should disappear from the AP after
4266 // commit();
4267
4268 PD_DocumentRDFMutationHandle m = createMutation();
4269 m->remove( PD_URI("http://www.example.com/koala"),
4270 PD_URI("http://www.example.com/is-a"),
4271 PD_Object("http://www.example.com/dangeroo"));
4272 m->remove( PD_URI("http://www.example.com/foo"),
4273 PD_URI("http://www.example.com/bar"),
4274 PD_Literal("AABBCC") );
4275
4276 }
4277 dumpModel();
4278
4279
4280 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() -------------------------------\n"));
4281 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test() rollback test\n"));
4282 {
4283 PD_DocumentRDFMutationHandle m = createMutation();
4284 m->add( PD_URI("http://www.example.com/et"),
4285 PD_URI("http://www.example.com/is-a"),
4286 PD_Object("http://www.example.com/alien"));
4287 m->rollback();
4288 }
4289 dumpModel();
4290
4291 runMilestone2Test2();
4292 #endif
4293 }
4294
4295 #ifdef DEBUG
dump(const std::string & msg,PD_RDFModelIterator iter,PD_RDFModelIterator e)4296 static void dump( const std::string& msg, PD_RDFModelIterator iter, PD_RDFModelIterator e )
4297 {
4298 int count = 0;
4299 UT_DEBUGMSG(("dump(top) msg::%s\n", msg.c_str() ));
4300 for( ; iter != e; ++iter )
4301 {
4302 const PD_RDFStatement& st(*iter);
4303 UT_DEBUGMSG((" st:%s\n", st.toString().c_str() ));
4304 ++count;
4305 }
4306 UT_DEBUGMSG(("dump(end) count:%d msg::%s\n", count, msg.c_str() ));
4307 }
4308 #endif
4309
4310
updateHaveSemItemsCache()4311 void PD_DocumentRDF::updateHaveSemItemsCache()
4312 {
4313 PD_RDFSemanticItems items = getAllSemanticObjects();
4314 m_haveSemItems = !items.empty();
4315 }
4316
haveSemItems() const4317 bool PD_DocumentRDF::haveSemItems() const
4318 {
4319 return m_haveSemItems;
4320 }
4321
4322
4323
runPlay()4324 void PD_DocumentRDF::runPlay()
4325 {
4326 #ifdef DEBUG
4327 UT_DEBUGMSG(("================================================================================\n" ));
4328 UT_DEBUGMSG(("PD_DocumentRDF::runPlay() o:%s\n", "foo" ));
4329
4330 PD_RDFContacts cl = getContacts();
4331 UT_DEBUGMSG(("PD_DocumentRDF::runPlay() contacts.sz:%lu\n", (long unsigned)cl.size() ));
4332
4333 for( PD_RDFContacts::iterator ci = cl.begin(); ci != cl.end(); ++ci )
4334 {
4335 PD_RDFContactHandle c = *ci;
4336
4337 UT_DEBUGMSG((" subj:%s\n", c->linkingSubject().toString().c_str() ));
4338 UT_DEBUGMSG((" name:%s\n", c->name().c_str() ));
4339 std::set< std::string > xmlids = c->getXMLIDs();
4340 for( std::set< std::string >::iterator iter = xmlids.begin(); iter != xmlids.end(); ++iter )
4341 {
4342 std::string xmlid = *iter;
4343 UT_DEBUGMSG((" x2mlid:%s ", xmlid.c_str() ));
4344 std::pair< PT_DocPosition, PT_DocPosition > range = getIDRange( xmlid );
4345 UT_DEBUGMSG((" start:%d end:%d ", range.first, range.second ));
4346 UT_DEBUGMSG((" \n" ));
4347 }
4348
4349
4350 // if( c->name() == "James Smith" )
4351 // {
4352 // c->showEditorWindow( c );
4353 // }
4354
4355 }
4356
4357 PD_RDFEvents el = getEvents();
4358 UT_DEBUGMSG((" events.sz:%lu\n", (long unsigned)el.size() ));
4359 for( PD_RDFEvents::iterator ei = el.begin(); ei != el.end(); ++ei )
4360 {
4361 PD_RDFEventHandle e = *ei;
4362 UT_DEBUGMSG((" events.name:%s\n", e->name().c_str() ));
4363
4364 if( e->name() == "uri:campingtime" )
4365 {
4366 e->showEditorWindow( e );
4367 }
4368 }
4369
4370
4371 return;
4372
4373
4374 UT_DebugOnly<int> count = 0;
4375 typedef PD_RDFModelIterator iterator;
4376 dump( "whole model", begin(), end() );
4377
4378 UT_DEBUGMSG(("runPlay() triple count:%d\n", (int)count ));
4379 UT_DEBUGMSG(("runPlay()\n\n"));
4380
4381 PD_RDFModelHandle m = getRDFForID( "wingb" );
4382 dump( "wingb", m->begin(), m->end() );
4383 #endif
4384 }
4385
4386
runMilestone2Test2()4387 void PD_DocumentRDF::runMilestone2Test2()
4388 {
4389 #ifdef DEBUG
4390 PD_URI s;
4391 PD_URI o = getObject( PD_URI("http://www.example.com/emu"),
4392 PD_URI("http://www.example.com/lives-in"));
4393 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() o:%s\n", o.toString().c_str()));
4394
4395 o = getObject( PD_URI("http://www.example.com/et"),
4396 PD_URI("http://www.example.com/is-a"));
4397 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() (should be nothing) o:%s\n", o.toString().c_str()));
4398
4399
4400 POCol col = getArcsOut( PD_URI("http://www.example.com/foo") );
4401 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() subject foo has arcs... count:%d\n", (int)col.size()));
4402 for( POCol::iterator iter = col .begin(); iter != col.end(); ++iter )
4403 {
4404 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() p:%s\n", iter->first.toString().c_str()));
4405 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() o:%s\n", iter->second.toString().c_str()));
4406 }
4407
4408 s = getSubject( PD_URI("http://www.example.com/lives-in"),
4409 PD_Object("http://www.example.com/australia"));
4410 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() one creature living in aus:%s\n", s.toString().c_str()));
4411
4412 PD_URIList ul = getSubjects( PD_URI("http://www.example.com/lives-in"),
4413 PD_Object("http://www.example.com/australia"));
4414 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() all of the creatures living in aus, count:%d\n",
4415 (int)ul.size()));
4416 for( PD_URIList::iterator iter = ul.begin(); iter != ul.end(); ++iter )
4417 {
4418 UT_DEBUGMSG(("PD_DocumentRDF::runMilestone2Test2() creature:%s\n", iter->toString().c_str()));
4419 }
4420
4421
4422 #endif
4423 }
4424
4425
dumpObjectMarkersFromDocument()4426 void PD_DocumentRDF::dumpObjectMarkersFromDocument()
4427 {
4428 #ifdef DEBUG
4429 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() doc:%p\n", m_doc));
4430 m_doc->dumpDoc("dumpObjectMarkersFromDocument", 0, 0);
4431
4432 PD_Document* doc = getDocument();
4433 pt_PieceTable* pt = getPieceTable();
4434 PT_DocPosition curr = 0;
4435 PT_DocPosition eod = 0;
4436 pt->getBounds( true, eod );
4437
4438 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() current:%d end:%d\n", curr, eod ));
4439
4440 for( ; curr < eod; ++curr )
4441 {
4442 pf_Frag* pf = 0;
4443 PT_BlockOffset boffset;
4444 pf_Frag_Strux* psdh;
4445 if( pt->getStruxOfTypeFromPosition( curr, PTX_Block, &psdh ) && psdh )
4446 {
4447 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() current:%d end:%d have PTX_BLOCK \n",
4448 curr, eod ));
4449 PT_AttrPropIndex api = doc->getAPIFromSDH( psdh );
4450 const PP_AttrProp * AP = NULL;
4451 doc->getAttrProp(api,&AP);
4452 if( AP )
4453 {
4454 const char * v = NULL;
4455 if(AP->getAttribute("xml:id",v))
4456 {
4457 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() xmlid:%s \n",v));
4458 }
4459 }
4460 }
4461
4462
4463
4464 if( pt->getFragFromPosition( curr, &pf, &boffset ) )
4465 {
4466 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() current:%d end:%d frag type:%d len:%d \n", curr, eod, pf->getType(), pf->getLength() ));
4467
4468 if(pf->getType() == pf_Frag::PFT_Object)
4469 {
4470 pf_Frag_Object* pOb = static_cast<pf_Frag_Object*>(pf);
4471
4472 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() po type:%d\n",
4473 pOb->getObjectType() ));
4474
4475 if(pOb->getObjectType() == PTO_RDFAnchor)
4476 {
4477 const PP_AttrProp * pAP = NULL;
4478 pOb->getPieceTable()->getAttrProp(pOb->getIndexAP(),&pAP);
4479
4480 const gchar * v = 0;
4481 if(!pAP->getAttribute(PT_XMLID, v) || !v)
4482 {
4483 }
4484 else
4485 {
4486 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() xml:id:%s\n",v));
4487 }
4488 if(pAP->getAttribute("this-is-an-rdf-anchor", v) && v) {
4489 UT_DEBUGMSG(("PD_DocumentRDF::dumpObjectMarkersFromDocument() is-rdf-a:%s\n",v));
4490 }
4491 }
4492 }
4493
4494 }
4495 }
4496
4497
4498 //////////////
4499
4500 // curr = 420;
4501 // PD_RDFModelHandle h = getRDFAtPosition( curr );
4502
4503 #endif
4504 }
4505
4506
4507 /**
4508 * Dump the model as debug messages
4509 */
dumpModel(const std::string & headerMsg)4510 void PD_DocumentRDF::dumpModel( const std::string& headerMsg )
4511 {
4512 UT_DEBUG_ONLY_ARG(headerMsg);
4513
4514 #ifdef DEBUG
4515 UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() doc:%p\n", m_doc));
4516 apDumpModel( getAP(), headerMsg );
4517 #endif
4518 }
4519
4520 void
maybeSetDocumentDirty()4521 PD_DocumentRDF::maybeSetDocumentDirty()
4522 {
4523 if( m_doc )
4524 m_doc->forceDirty();
4525
4526 incremenetVersion();
4527 }
4528
4529
4530 /**
4531 * Dump the model contained in the given AP as debug messages
4532 */
4533 void
apDumpModel(const PP_AttrProp * AP,const std::string & headerMsg)4534 PD_DocumentRDF::apDumpModel( const PP_AttrProp* AP, const std::string& headerMsg )
4535 {
4536 UT_DEBUG_ONLY_ARG(AP);
4537 UT_DEBUG_ONLY_ARG(headerMsg);
4538
4539 #ifdef DEBUG
4540 UT_DEBUGMSG(("PD_DocumentRDF::apDumpModel() ----------------------------------\n"));
4541 UT_DEBUGMSG(("PD_DocumentRDF::apDumpModel() %s\n", headerMsg.c_str()));
4542 UT_DEBUGMSG(("PD_DocumentRDF::apDumpModel() triple count:%ld\n", getTripleCount()));
4543 UT_DEBUGMSG(("PD_DocumentRDF::apDumpModel() ----------------------------------\n"));
4544
4545 size_t count = AP->getPropertyCount();
4546 UT_DEBUGMSG(("PD_DocumentRDF::DUMPMODEL() API:%d COUNT:%ld\n", m_indexAP, (long)count));
4547 for( size_t i = 0; i < count; ++i )
4548 {
4549 const gchar * szName = 0;
4550 const gchar * szValue = 0;
4551 if( AP->getNthProperty( i, szName, szValue) )
4552 {
4553 // UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() szName :%s\n", szName ));
4554 // UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() szValue:%s\n", szValue ));
4555
4556 POCol l = decodePOCol( szValue );
4557 // UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() po list size:%d\n", (int)l.size() ));
4558 std::string subj = szName;
4559 for( POCol::iterator iter = l.begin(); iter!=l.end(); ++iter )
4560 {
4561 std::string pred = iter->first.toString();
4562 std::string obj = iter->second.toString();
4563 UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() s:%s\n",
4564 subj.c_str()));
4565 UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() p:%s\n",
4566 pred.c_str()));
4567 UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() ot:%d o:%s\n",
4568 iter->second.getObjectType(), obj.c_str()));
4569 if( iter->second.hasXSDType() )
4570 {
4571 UT_DEBUGMSG(("PD_DocumentRDF::dumpModel() type:%s\n",
4572 iter->second.getXSDType().c_str()));
4573 }
4574 }
4575 }
4576 }
4577 #endif
4578 }
4579
4580 /****************************************/
4581 /****************************************/
4582 /****************************************/
4583 /****************************************/
4584 /****************************************/
4585 /****************************************/
4586
4587
4588 /**
4589 * A view on the given delegate model, restricted to showing only the
4590 * triples which match a given SPARQL query. For dynamicaly created
4591 * queries, a subclass might overload getSparql() and make the query
4592 * string at runtime.
4593 *
4594 * Subclasses might decide to override createMutation() to adjust
4595 * things when changes are desired.
4596 */
4597 class RDFModel_SPARQLLimited
4598 :
4599 public PD_RDFModelFromAP
4600 {
4601 protected:
4602
4603 PD_DocumentRDFHandle m_rdf;
4604 PD_RDFModelHandle m_delegate;
4605 std::string m_sparql;
4606
4607 protected:
4608 virtual void update();
4609
4610 public:
4611
RDFModel_SPARQLLimited(PD_DocumentRDFHandle rdf,PD_RDFModelHandle delegate)4612 RDFModel_SPARQLLimited( PD_DocumentRDFHandle rdf,
4613 PD_RDFModelHandle delegate )
4614 : PD_RDFModelFromAP( rdf->getDocument(), new PP_AttrProp() )
4615 , m_rdf( rdf )
4616 , m_delegate( delegate )
4617 {
4618 }
~RDFModel_SPARQLLimited()4619 virtual ~RDFModel_SPARQLLimited()
4620 {
4621 }
4622 virtual PD_DocumentRDFMutationHandle createMutation();
getSparql()4623 virtual std::string getSparql()
4624 {
4625 return m_sparql;
4626 }
4627
4628
setSparql(const std::string & s)4629 void setSparql( const std::string& s )
4630 {
4631 m_sparql = s;
4632 }
4633
getAP(void)4634 virtual const PP_AttrProp* getAP(void)
4635 {
4636 update();
4637 return m_AP;
4638 }
4639
4640 };
4641
4642 PD_DocumentRDFMutationHandle
createMutation()4643 RDFModel_SPARQLLimited::createMutation()
4644 {
4645 PD_DocumentRDFMutationHandle ret;
4646 return ret;
4647 }
4648
4649 void
update()4650 RDFModel_SPARQLLimited::update()
4651 {
4652 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() TOP\n" ));
4653 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() our version:%ld\n", getVersion() ));
4654 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() their version:%ld\n", m_delegate->getVersion() ));
4655
4656 if( getVersion() >= m_delegate->getVersion() )
4657 {
4658 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() nothing to be done...\n" ));
4659 return;
4660 }
4661
4662 PP_AttrProp* AP = new PP_AttrProp();
4663 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() 1\n" ));
4664 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() sparql:%s\n", getSparql().c_str() ));
4665
4666 PD_RDFQuery q( m_rdf, m_delegate );
4667 PD_ResultBindings_t bindings = q.executeQuery( getSparql() );
4668 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() 2\n" ));
4669
4670 for( PD_ResultBindings_t::iterator iter = bindings.begin(); iter != bindings.end(); ++iter )
4671 {
4672 std::map< std::string, std::string > d = *iter;
4673
4674 PD_URI s( d["s"] );
4675 PD_URI p( d["p"] );
4676
4677 int objectType = PD_Object::OBJECT_TYPE_URI;
4678 PD_Object dobj = m_delegate->getObject( s, p );
4679 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() dobj.valid:%d dobj.type:%d dobj.str:%s \n",
4680 dobj.isValid(),
4681 dobj.getObjectType(),
4682 dobj.toString().c_str() ));
4683 if( dobj.isValid() )
4684 objectType = dobj.getObjectType();
4685
4686 PD_Object o( d["o"], objectType );
4687
4688
4689 POCol l;
4690 const gchar* szName = s.toString().c_str();
4691 const gchar* szValue = 0;
4692 if( AP->getProperty( szName, szValue) )
4693 {
4694 l = decodePOCol(szValue);
4695 }
4696 l.insert( std::make_pair( p, o ));
4697 std::string po = encodePOCol(l);
4698 AP->setProperty( szName, po.c_str() );
4699
4700 PD_RDFStatement st( s, p, o );
4701 UT_DEBUGMSG(("RDFModel_SPARQLLimited::update() adding st:%s \n", st.toString().c_str() ));
4702 }
4703
4704 delete m_AP;
4705 m_AP = AP;
4706 m_version = m_delegate->getVersion();
4707
4708 // dumpModel("after sparql query...");
4709 }
4710
4711 /****************************************/
4712 /****************************************/
4713 /****************************************/
4714
4715
4716 class RDFModel_XMLIDLimited
4717 :
4718 public RDFModel_SPARQLLimited
4719 {
4720 std::string m_writeID;
4721 std::set< std::string > m_readIDList;
4722 protected:
4723 virtual void update();
4724
4725 public:
4726
RDFModel_XMLIDLimited(PD_DocumentRDFHandle rdf,PD_RDFModelHandle delegate,const std::string & writeID,const std::set<std::string> & readIDList)4727 RDFModel_XMLIDLimited( PD_DocumentRDFHandle rdf,
4728 PD_RDFModelHandle delegate,
4729 const std::string& writeID,
4730 const std::set< std::string >& readIDList )
4731 : RDFModel_SPARQLLimited( rdf, delegate )
4732 , m_writeID( writeID )
4733 , m_readIDList( readIDList )
4734 {
4735 }
4736
~RDFModel_XMLIDLimited()4737 virtual ~RDFModel_XMLIDLimited()
4738 {
4739 UT_DEBUGMSG(("~RDFModel_XMLIDLimited()\n"));
4740 }
4741
4742 virtual std::string getSparql();
4743 virtual PD_DocumentRDFMutationHandle createMutation();
4744 };
4745
4746 void
update()4747 RDFModel_XMLIDLimited::update()
4748 {
4749 if( getVersion() >= m_delegate->getVersion() )
4750 {
4751 UT_DEBUGMSG(("RDFModel_XMLIDLimited::update() nothing to be done...\n" ));
4752 return;
4753 }
4754
4755 std::set< std::string > xmlids;
4756 xmlids.insert( m_writeID );
4757 copy( m_readIDList.begin(), m_readIDList.end(), inserter( xmlids, xmlids.end() ) );
4758
4759 if( xmlids.size() == 1 )
4760 {
4761 std::string xmlid = *(xmlids.begin());
4762 PP_AttrProp* AP = new PP_AttrProp();
4763
4764 PD_URI idref( "http://docs.oasis-open.org/opendocument/meta/package/common#pkg:idref" );
4765 PD_Literal rdflink( xmlid );
4766 PD_URI s = m_delegate->getSubject( idref, rdflink );
4767 POCol polist = m_delegate->getArcsOut( s );
4768
4769 const gchar* szName = s.toString().c_str();
4770 std::string po = encodePOCol( polist );
4771 AP->setProperty( szName, po.c_str() );
4772 return;
4773 }
4774
4775 RDFModel_SPARQLLimited::update();
4776 }
4777
4778
4779 std::string
getSparql()4780 RDFModel_XMLIDLimited::getSparql()
4781 {
4782 UT_DEBUGMSG(("RDFModel_XMLIDLimited::getSparql()\n"));
4783 std::set< std::string > xmlids;
4784 xmlids.insert( m_writeID );
4785 copy( m_readIDList.begin(), m_readIDList.end(), inserter( xmlids, xmlids.end() ) );
4786 std::string sparql = PD_DocumentRDF::getSPARQL_LimitedToXMLIDList( xmlids );
4787 return sparql;
4788 }
4789
4790
4791 class ABI_EXPORT PD_RDFMutation_XMLIDLimited
4792 :
4793 public PD_DocumentRDFMutation
4794 {
4795 PD_DocumentRDFMutationHandle m_delegate;
4796 std::string m_writeID;
4797 typedef std::set< std::string > m_cleanupSubjects_t;
4798 m_cleanupSubjects_t m_cleanupSubjects;
4799
4800 public:
PD_RDFMutation_XMLIDLimited(PD_DocumentRDF * rdf,PD_DocumentRDFMutationHandle delegate,const std::string & xmlid)4801 PD_RDFMutation_XMLIDLimited( PD_DocumentRDF* rdf,
4802 PD_DocumentRDFMutationHandle delegate,
4803 const std::string& xmlid )
4804 : PD_DocumentRDFMutation( rdf )
4805 , m_delegate( delegate )
4806 , m_writeID( xmlid )
4807 {
4808 }
4809
add(const PD_URI & s,const PD_URI & p,const PD_Object & o)4810 virtual bool add( const PD_URI& s, const PD_URI& p, const PD_Object& o )
4811 {
4812 UT_DEBUGMSG(("XMLIDLimited::add() s:%s\n", s.toString().c_str() ));
4813 UT_DEBUGMSG(("XMLIDLimited::add() p:%s\n", p.toString().c_str() ));
4814 UT_DEBUGMSG(("XMLIDLimited::add() o:%s\n", o.toString().c_str() ));
4815 UT_DEBUGMSG(("XMLIDLimited::add() s:%s linking to xmlid:%s\n",
4816 s.toString().c_str(), m_writeID.c_str() ));
4817
4818 bool rc = true;
4819 rc &= m_delegate->add( s, p, o );
4820 if( !rc )
4821 return rc;
4822
4823
4824 PD_RDFStatement rdflink( s,
4825 PD_URI("http://docs.oasis-open.org/opendocument/meta/package/common#idref"),
4826 PD_Literal(m_writeID) );
4827 UT_DEBUGMSG(("XMLIDLimited::add() testing document for existing rdflink\n" ));
4828 if( !m_rdf->contains( rdflink ))
4829 {
4830 UT_DEBUGMSG(("XMLIDLimited::add() document does not contain the rdflink\n" ));
4831 rc &= m_delegate->add( rdflink );
4832 }
4833
4834 UT_DEBUGMSG(("XMLIDLimited::add() s:%s linking to xmlid:%s rc:%d\n",
4835 s.toString().c_str(), m_writeID.c_str(), rc ));
4836 return rc;
4837
4838 }
remove(const PD_URI & s,const PD_URI & p,const PD_Object & o)4839 virtual void remove( const PD_URI& s, const PD_URI& p, const PD_Object& o )
4840 {
4841 POCol po = m_rdf->getArcsOut( s );
4842 UT_DEBUGMSG(("XMLIDLimited::remove() subject count:%d\n", (int)po.size() ));
4843
4844 m_delegate->remove( s, p, o );
4845 m_cleanupSubjects.insert( s.toString() );
4846 }
commit()4847 virtual UT_Error commit()
4848 {
4849 UT_DEBUGMSG(("XMLIDLimited::commit()\n" ));
4850 UT_Error ret = m_delegate->commit();
4851
4852 //
4853 // Check the subjects that were deleted to see if they are now only
4854 // involved in triples like
4855 // s pkg:idref ?xmlid
4856 //
4857 for( m_cleanupSubjects_t::iterator iter = m_cleanupSubjects.begin();
4858 iter != m_cleanupSubjects.end(); ++iter )
4859 {
4860 std::string subj = *iter;
4861
4862 std::stringstream sparql;
4863 sparql << "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
4864 << "prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
4865 << "prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#> \n"
4866 << "prefix geo84: <http://www.w3.org/2003/01/geo/wgs84_pos#> \n"
4867 << " \n"
4868 << "select ?s ?p ?o ?rdflink \n"
4869 << "where { \n"
4870 << " ?s ?p ?o . \n"
4871 << " ?s pkg:idref ?rdflink . \n"
4872 << " filter( str(?s) = \"" << subj << "\" ) . \n"
4873 << " filter( str(?p) != \"http://docs.oasis-open.org/opendocument/meta/package/common#idref\" ) \n"
4874 << "} \n";
4875
4876
4877 // std::list< std::string > xmlids;
4878 // xmlids.push_back( xmlid );
4879 // std::string sparql = PD_DocumentRDF::getSPARQL_LimitedToXMLIDList(
4880 // xmlids,
4881 // "filter( str(?p) != \"http://docs.oasis-open.org/opendocument/meta/package/common#idref\" ) " );
4882 PD_DocumentRDFHandle rdf = m_rdf->getDocument()->getDocumentRDF();
4883 PD_RDFQuery q( rdf, rdf );
4884 PD_ResultBindings_t bindings = q.executeQuery( sparql.str() );
4885
4886
4887 UT_DEBUGMSG(("XMLIDLimited::commit() subj:%s bindings.count:%d\n",
4888 subj.c_str(), (int)bindings.size() ));
4889
4890 if( bindings.empty() )
4891 {
4892 PD_URI s(subj);
4893 PD_URI idref("http://docs.oasis-open.org/opendocument/meta/package/common#idref");
4894 UT_DEBUGMSG(("XMLIDLimited::commit() can remove links for subj:%s\n", subj.c_str() ));
4895
4896 PD_ObjectList ul = rdf->getObjects( subj, idref );
4897 PD_DocumentRDFMutationHandle m = rdf->createMutation();
4898 for( PD_ObjectList::iterator iter2 = ul.begin(); iter2 != ul.end(); ++iter2 )
4899 {
4900 m->remove( s, idref, *iter2 );
4901 }
4902 m->commit();
4903 }
4904 }
4905
4906 return ret;
4907 }
4908
rollback()4909 virtual void rollback()
4910 {
4911 m_delegate->rollback();
4912 }
4913
4914
4915
4916 };
4917
4918
4919 PD_DocumentRDFMutationHandle
createMutation()4920 RDFModel_XMLIDLimited::createMutation()
4921 {
4922 UT_DEBUGMSG(("XMLIDLimited::createMutation()\n"));
4923
4924 PD_DocumentRDFMutationHandle dmodel = m_delegate->createMutation();
4925 PD_DocumentRDFMutationHandle ret(
4926 new PD_RDFMutation_XMLIDLimited( dmodel->m_rdf,
4927 dmodel,
4928 m_writeID ));
4929 return ret;
4930 }
4931
4932
4933 PD_RDFModelHandle
createRestrictedModelForXMLIDs(const std::string & writeID,const std::set<std::string> & xmlids)4934 PD_DocumentRDF::createRestrictedModelForXMLIDs( const std::string& writeID,
4935 const std::set< std::string >& xmlids )
4936 {
4937 UT_DEBUGMSG(("createRestrictedModelForXMLIDs() writeID:%s xmlids.sz:%d\n",
4938 writeID.c_str(), (int)xmlids.size() ));
4939
4940 PD_DocumentRDFHandle rdf = getDocument()->getDocumentRDF();
4941 PD_RDFModelHandle model = rdf;
4942
4943 PD_RDFModelHandle ret(new RDFModel_XMLIDLimited( rdf, model, writeID, xmlids ));
4944 return ret;
4945 }
4946
4947 PD_RDFModelHandle
createRestrictedModelForXMLIDs(const std::set<std::string> & xmlids)4948 PD_DocumentRDF::createRestrictedModelForXMLIDs( const std::set< std::string >& xmlids )
4949 {
4950 std::string writeID = "";
4951 if( !xmlids.empty() )
4952 writeID = *(xmlids.begin());
4953 return createRestrictedModelForXMLIDs( writeID, xmlids );
4954 }
4955
4956 PD_RDFSemanticItems
getAllSemanticObjects(const std::string & classRestriction)4957 PD_DocumentRDF::getAllSemanticObjects( const std::string& classRestriction )
4958 {
4959 PD_RDFSemanticItems ret;
4960 if( classRestriction.empty() || classRestriction == "Contact" )
4961 {
4962 PD_RDFContacts contacts = getContacts();
4963 copy( contacts.begin(), contacts.end(), back_inserter(ret));
4964 }
4965
4966 if( classRestriction.empty() || classRestriction == "Event" )
4967 {
4968 PD_RDFEvents events = getEvents();
4969 copy( events.begin(), events.end(), back_inserter(ret));
4970 }
4971
4972 if( classRestriction.empty() || classRestriction == "Location" )
4973 {
4974 PD_RDFLocations locations = getLocations();
4975 copy( locations.begin(), locations.end(), back_inserter(ret));
4976 }
4977
4978 return ret;
4979 }
4980
4981
4982
4983 PD_RDFSemanticItems
getSemanticObjects(const std::set<std::string> & xmlids)4984 PD_DocumentRDF::getSemanticObjects( const std::set< std::string >& xmlids )
4985 {
4986 PD_RDFSemanticItems ret;
4987
4988 PD_RDFContacts contacts = getContacts();
4989 for( PD_RDFContacts::iterator ci = contacts.begin();
4990 ci != contacts.end(); ++ci )
4991 {
4992 PD_RDFContactHandle c = *ci;
4993 std::set< std::string > clist = c->getXMLIDs();
4994 std::set< std::string > tmp;
4995 std::set_intersection( xmlids.begin(), xmlids.end(),
4996 clist.begin(), clist.end(),
4997 inserter( tmp, tmp.end() ));
4998 if( !tmp.empty() )
4999 {
5000 ret.push_back( c );
5001 }
5002 }
5003
5004 PD_RDFEvents events = getEvents();
5005 for( PD_RDFEvents::iterator ci = events.begin();
5006 ci != events.end(); ++ci )
5007 {
5008 PD_RDFEventHandle c = *ci;
5009 std::set< std::string > clist = c->getXMLIDs();
5010 std::set< std::string > tmp;
5011 std::set_intersection( xmlids.begin(), xmlids.end(),
5012 clist.begin(), clist.end(),
5013 inserter( tmp, tmp.end() ));
5014 if( !tmp.empty() )
5015 {
5016 ret.push_back( c );
5017 }
5018 }
5019
5020 PD_RDFLocations locations = getLocations();
5021 for( PD_RDFLocations::iterator ci = locations.begin();
5022 ci != locations.end(); ++ci )
5023 {
5024 PD_RDFLocationHandle c = *ci;
5025 std::set< std::string > clist = c->getXMLIDs();
5026 std::set< std::string > tmp;
5027 std::set_intersection( xmlids.begin(), xmlids.end(),
5028 clist.begin(), clist.end(),
5029 inserter( tmp, tmp.end() ));
5030 if( !tmp.empty() )
5031 {
5032 ret.push_back( c );
5033 }
5034 }
5035
5036 return ret;
5037 }
5038
5039
5040
5041
5042
5043 void
selectXMLIDs(const std::set<std::string> & xmlids,FV_View * pView) const5044 PD_DocumentRDF::selectXMLIDs( const std::set< std::string >& xmlids, FV_View* pView ) const
5045 {
5046 XAP_Frame* lff = XAP_App::getApp()->getLastFocussedFrame();
5047 if( !pView && lff )
5048 pView = static_cast<FV_View*>( lff->getCurrentView() );
5049 if( !pView )
5050 return;
5051
5052 for( std::set< std::string >::const_iterator iter = xmlids.begin(); iter != xmlids.end(); ++iter )
5053 {
5054 const std::string& xmlid = *iter;
5055 std::pair< PT_DocPosition, PT_DocPosition > range = getIDRange( xmlid );
5056 UT_DEBUGMSG(("selectXMLIDs() id:%s begin:%d end:%d\n",
5057 xmlid.c_str(), range.first, range.second ));
5058 if( range.first && range.second > range.first )
5059 pView->selectRange( range );
5060 }
5061 }
5062
5063 void
showEditorWindow(const PD_RDFSemanticItems & cl)5064 PD_DocumentRDF::showEditorWindow( const PD_RDFSemanticItems & cl )
5065 {
5066 if( !cl.empty() )
5067 {
5068 PD_RDFSemanticItems::const_iterator ci = cl.begin();
5069 PD_RDFSemanticItemHandle c = *ci;
5070 c->showEditorWindow( cl );
5071 }
5072 }
5073
5074
5075
5076 PD_RDFContacts
getContacts(PD_RDFModelHandle alternateModel)5077 PD_DocumentRDF::getContacts( PD_RDFModelHandle alternateModel )
5078 {
5079 PD_RDFModelHandle m = alternateModel;
5080 if( !m )
5081 m = getDocument()->getDocumentRDF();
5082
5083 PD_RDFContacts ret;
5084 std::stringstream sparqlQuery;
5085 sparqlQuery << "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
5086 << "prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
5087 << "prefix pkg: <http://docs.oasis-open.org/opendocument/meta/package/common#> \n"
5088 << "select distinct ?person ?name ?nick ?email ?homepage ?img ?phone \n"
5089 << "where { \n"
5090 << " ?person rdf:type foaf:Person . \n"
5091 << " ?person foaf:name ?name \n"
5092 << " OPTIONAL { ?person foaf:phone ?phone } \n"
5093 << " OPTIONAL { ?person foaf:mbox ?email } \n"
5094 << " OPTIONAL { ?person foaf:nick ?nick } \n"
5095 << " OPTIONAL { ?person foaf:homepage ?homepage } \n"
5096 << " OPTIONAL { ?person foaf:img ?img } \n"
5097 << "}\n";
5098 UT_DEBUGMSG(("getContacts() sparql:\n%s\n\n", sparqlQuery.str().c_str() ));
5099
5100 PD_DocumentRDFHandle rdf = getDocument()->getDocumentRDF();
5101 PD_RDFQuery q( rdf, m );
5102 PD_ResultBindings_t bindings = q.executeQuery( sparqlQuery.str() );
5103 UT_DEBUGMSG(("getContacts() bindings.sz:%lu\n", (long unsigned)bindings.size() ));
5104
5105 // uniqfilter is needed because redland might not honour the
5106 // DISTINCT sparql keyword
5107 std::set<std::string> uniqfilter;
5108 for( PD_ResultBindings_t::iterator it = bindings.begin(); it != bindings.end(); ++it )
5109 {
5110 std::string n = (*it)["name"];
5111 if (uniqfilter.count(n))
5112 continue;
5113 uniqfilter.insert(n);
5114
5115 PD_RDFContact* newItem = PD_DocumentRDF::getSemanticItemFactory()->createContact( rdf, it );
5116 PD_RDFContactHandle h( newItem );
5117 ret.push_back( h );
5118 }
5119
5120 return ret;
5121 }
5122
5123
5124 PD_RDFEvents
getEvents(PD_RDFModelHandle alternateModel)5125 PD_DocumentRDF::getEvents( PD_RDFModelHandle alternateModel )
5126 {
5127 PD_RDFModelHandle m = alternateModel;
5128 if( !m )
5129 m = getDocument()->getDocumentRDF();
5130
5131 PD_RDFEvents ret;
5132 std::stringstream sparqlQuery;
5133 sparqlQuery << " prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
5134 << " prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
5135 << " prefix cal: <http://www.w3.org/2002/12/cal/icaltzd#> \n"
5136 << " select distinct ?ev ?uid ?dtstart ?dtend ?summary ?location ?description ?geo ?long ?lat \n"
5137 << " where { \n"
5138 << " ?ev rdf:type cal:Vevent . \n"
5139 << " ?ev cal:uid ?uid . \n"
5140 << " ?ev cal:dtstart ?dtstart . \n"
5141 << " ?ev cal:dtend ?dtend \n"
5142 << " OPTIONAL { ?ev cal:summary ?summary } \n"
5143 << " OPTIONAL { ?ev cal:location ?location } \n"
5144 << " OPTIONAL { ?ev cal:description ?description } \n"
5145 << " OPTIONAL { \n"
5146 << " ?ev cal:geo ?geo . \n"
5147 << " ?geo rdf:first ?lat . \n"
5148 << " ?geo rdf:rest ?joiner . \n"
5149 << " ?joiner rdf:first ?long \n"
5150 << " } \n"
5151 << " } \n";
5152
5153 UT_DEBUGMSG(("getEvents() sparql:\n%s\n\n", sparqlQuery.str().c_str() ));
5154
5155 PD_DocumentRDFHandle rdf = getDocument()->getDocumentRDF();
5156 PD_RDFQuery q( rdf, m );
5157 PD_ResultBindings_t bindings = q.executeQuery( sparqlQuery.str() );
5158 UT_DEBUGMSG(("getEvents() bindings.sz:%lu\n", (long unsigned)bindings.size() ));
5159
5160 // uniqfilter is needed because redland might not honour the
5161 // DISTINCT sparql keyword
5162 std::set<std::string> uniqfilter;
5163 for( PD_ResultBindings_t::iterator it = bindings.begin(); it != bindings.end(); ++it )
5164 {
5165 std::string n = (*it)["uid"];
5166 if (uniqfilter.count(n))
5167 continue;
5168 uniqfilter.insert(n);
5169
5170 PD_RDFEvent* newItem = PD_DocumentRDF::getSemanticItemFactory()->createEvent( rdf, it );
5171 PD_RDFEventHandle h( newItem );
5172 ret.push_back( h );
5173 }
5174
5175 return ret;
5176 }
5177
5178
5179 PD_RDFLocations&
addLocations(PD_RDFLocations & ret,bool isGeo84,const std::string sparql,PD_RDFModelHandle)5180 PD_DocumentRDF::addLocations( PD_RDFLocations& ret,
5181 bool isGeo84,
5182 const std::string sparql,
5183 PD_RDFModelHandle /*alternateModel*/ )
5184 {
5185 PD_DocumentRDFHandle rdf = getDocument()->getDocumentRDF();
5186 PD_RDFQuery q( rdf, rdf );
5187 PD_ResultBindings_t bindings = q.executeQuery( sparql );
5188 UT_DEBUGMSG(("addLocations() bindings.sz:%lu sparql\n%s\n", (long unsigned)bindings.size(), sparql.c_str() ));
5189 std::set<std::string> uniqfilter;
5190 for( PD_ResultBindings_t::iterator it = bindings.begin(); it != bindings.end(); ++it )
5191 {
5192 std::string n = (*it)["lat"];
5193 if (uniqfilter.count(n))
5194 continue;
5195 uniqfilter.insert(n);
5196 UT_DEBUGMSG(("addLocations() n:%s\n", n.c_str() ));
5197
5198 #ifdef WITH_CHAMPLAIN
5199 PD_RDFLocation* newItem = PD_DocumentRDF::getSemanticItemFactory()->createLocation( rdf, it, isGeo84 );
5200 PD_RDFLocationHandle h( newItem );
5201 ret.push_back( h );
5202 #else
5203 UT_UNUSED( isGeo84 );
5204 #endif
5205 }
5206 return ret;
5207 }
5208
5209
5210 PD_RDFLocations
getLocations(PD_RDFModelHandle alternateModel)5211 PD_DocumentRDF::getLocations( PD_RDFModelHandle alternateModel )
5212 {
5213 PD_RDFLocations ret;
5214 addLocations( ret, false,
5215 " prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
5216 " prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
5217 " prefix dc: <http://purl.org/dc/elements/1.1/> \n"
5218 " prefix cal: <http://www.w3.org/2002/12/cal/icaltzd#> \n"
5219 " select distinct ?geo ?long ?lat ?joiner ?desc \n"
5220 " where { \n"
5221 " ?ev cal:geo ?geo . \n"
5222 " ?geo rdf:first ?lat . \n"
5223 " ?geo rdf:rest ?joiner . \n"
5224 " ?joiner rdf:first ?long \n"
5225 " OPTIONAL { ?geo dc:title ?desc } \n"
5226 " } \n", alternateModel );
5227 UT_DEBUGMSG(( "getLocations(1) ret.size:%lu\n", (long unsigned)ret.size() ));
5228
5229 addLocations( ret, true,
5230 " prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
5231 " prefix dc: <http://purl.org/dc/elements/1.1/> \n"
5232 " prefix foaf: <http://xmlns.com/foaf/0.1/> \n"
5233 " prefix geo84: <http://www.w3.org/2003/01/geo/wgs84_pos#> \n"
5234 " \n"
5235 " select distinct ?geo ?long ?lat ?type ?desc \n"
5236 " where { \n"
5237 " \n"
5238 " ?geo geo84:lat ?lat . \n"
5239 " ?geo geo84:long ?long \n"
5240 " OPTIONAL { ?geo rdf:type ?type } \n"
5241 " OPTIONAL { ?geo dc:title ?desc } \n"
5242 " \n"
5243 " } \n", alternateModel );
5244 UT_DEBUGMSG(( "getLocations(2) ret.size:%lu\n", (long unsigned)ret.size() ));
5245
5246 return ret;
5247 }
5248
5249 /****************************************/
5250 /****************************************/
5251 /****************************************/
5252 /****************************************/
5253 /****************************************/
5254 /****************************************/
5255
PD_DocumentRDFMutation(PD_DocumentRDF * rdf)5256 PD_DocumentRDFMutation::PD_DocumentRDFMutation( PD_DocumentRDF* rdf )
5257 : m_rdf(rdf)
5258 , m_rolledback(false)
5259 , m_committed(false)
5260 , m_handlingAbiCollabNotification( false )
5261 , m_pAP( 0 )
5262 {
5263 m_pAP = m_rdf->getAP()->cloneWithReplacements( 0, 0, false );
5264 m_crRemoveAP = new PP_AttrProp();
5265 m_crAddAP = new PP_AttrProp();
5266
5267 UT_DEBUGMSG(("PD_DocumentRDF::ctor() this:%p rdf:%p\n", this, m_rdf));
5268 }
5269
~PD_DocumentRDFMutation()5270 PD_DocumentRDFMutation::~PD_DocumentRDFMutation()
5271 {
5272 if( !m_committed )
5273 commit();
5274
5275 if(m_pAP)
5276 delete m_pAP;
5277 if(m_crRemoveAP)
5278 delete m_crRemoveAP;
5279 if(m_crAddAP)
5280 delete m_crAddAP;
5281 }
5282
apAdd(PP_AttrProp * AP,const PD_URI & s,const PD_URI & p,const PD_Object & o)5283 bool PD_DocumentRDFMutation::apAdd( PP_AttrProp* AP, const PD_URI& s, const PD_URI& p, const PD_Object& o )
5284 {
5285 POCol l;
5286 const gchar* szName = s.toString().c_str();
5287 const gchar* szValue = 0;
5288 if( AP->getProperty( szName, szValue) )
5289 {
5290 l = decodePOCol(szValue);
5291 }
5292
5293 // don't do this... it doesn't allow a (s,p) to have multiple objects at a global scale.
5294 // for( POCol::iterator iter = l.find( p ); iter != l.end(); iter = l.find( p ) )
5295 // {
5296 // l.erase( iter );
5297 // }
5298 l.insert( std::make_pair( p, o ));
5299 std::string po = encodePOCol(l);
5300 return AP->setProperty( szName, po.c_str() );
5301 }
5302
apRemove(PP_AttrProp * & AP,const PD_URI & s,const PD_URI & p,const PD_Object & o)5303 void PD_DocumentRDFMutation::apRemove( PP_AttrProp*& AP, const PD_URI& s, const PD_URI& p, const PD_Object& o )
5304 {
5305 PP_AttrProp* newAP = new PP_AttrProp();
5306 size_t propCount = AP->getPropertyCount();
5307 for( size_t i = 0; i<propCount; ++i )
5308 {
5309 const gchar * szName = 0;
5310 const gchar * szValue = 0;
5311
5312 if( !AP->getNthProperty( i, szName, szValue))
5313 {
5314 // failed to get old prop
5315 continue;
5316 }
5317
5318 if( s.toString() == szName )
5319 {
5320 // drop this triple...
5321 POCol l = decodePOCol(szValue);
5322 std::pair< POCol::iterator, POCol::iterator > range
5323 = std::equal_range( l.begin(), l.end(), p );
5324 for( POCol::iterator iter = range.first; iter != range.second; )
5325 {
5326 if( iter->first == p && iter->second == o )
5327 {
5328 POCol::iterator t = iter;
5329 ++iter;
5330 l.erase(t);
5331 continue;
5332 }
5333 ++iter;
5334 }
5335
5336 std::string po = encodePOCol(l);
5337 // commit() calls prune first, so this property
5338 // will disappear from the AP if it's list is empty
5339 if(l.empty())
5340 po = "";
5341
5342 if( !newAP->setProperty( szName, po.c_str() ))
5343 {
5344 // FIXME: failed to copy prop
5345 }
5346
5347 continue;
5348 }
5349
5350 if( !newAP->setProperty( szName, szValue ))
5351 {
5352 // FIXME: failed to copy prop
5353 }
5354 }
5355
5356 std::swap( AP, newAP );
5357 delete newAP;
5358 }
5359
5360
5361 bool
add(const PD_URI & s,const PD_URI & p,const PD_Object & o)5362 PD_DocumentRDFMutation::add( const PD_URI& s, const PD_URI& p, const PD_Object& o )
5363 {
5364 UT_DEBUGMSG(("PD_DocumentRDFMutation::add(1) s:%s o:%s ot:%d\n",
5365 s.toString().c_str(), o.toString().c_str(), o.getObjectType() ));
5366 // If it already exists and was not removed
5367 // then you can't add it again
5368 if( m_rdf->contains( s, p, o ) && !m_rdf->apContains( m_crRemoveAP, s, p, o ))
5369 return true;
5370
5371 // If this mutation has added it but not already committed that addition
5372 // to the document then do not add it again either
5373 if( m_rdf->apContains( m_crAddAP, s, p, o ) && !m_rdf->apContains( m_crRemoveAP, s, p, o ))
5374 return true;
5375
5376 UT_DEBUGMSG(("PD_DocumentRDFMutation::add(2) s:%s o:%s\n", s.toString().c_str(), o.toString().c_str() ));
5377
5378 apAdd( m_pAP, s, p, o );
5379 apAdd( m_crAddAP, s, p, o );
5380 return true;
5381 }
5382
5383 bool
add(const PD_URI & s,const PD_URI & p,const PD_Object & o,const PD_URI &)5384 PD_DocumentRDFMutation::add( const PD_URI& s, const PD_URI& p, const PD_Object& o, const PD_URI& /*context*/ )
5385 {
5386 return add( s, p, o );
5387 }
5388
5389
5390 void
remove(const PD_URI & s,const PD_URI & p,const PD_Object & o)5391 PD_DocumentRDFMutation::remove( const PD_URI& s, const PD_URI& p, const PD_Object& o )
5392 {
5393 UT_DEBUGMSG(("PD_DocumentRDFMutation::remove(1) s:%s p:%s o:%s ot:%d\n",
5394 s.toString().c_str(), p.c_str(), o.toString().c_str(), o.getObjectType() ));
5395
5396 apRemove( m_pAP, s, p, o );
5397 apRemove( m_crAddAP, s, p, o );
5398 apAdd( m_crRemoveAP, s, p, o );
5399 }
5400
5401 void
remove(const PD_URI & s,const PD_URI & p,const PD_URI & o)5402 PD_DocumentRDFMutation::remove( const PD_URI& s, const PD_URI& p, const PD_URI& o )
5403 {
5404 remove( s, p, PD_Object( o.toString() ));
5405 }
5406
5407
5408 bool
add(const PD_RDFStatement & st)5409 PD_DocumentRDFMutation::add( const PD_RDFStatement& st )
5410 {
5411 return add( st.getSubject(), st.getPredicate(), st.getObject() );
5412 }
5413
5414 PD_URI
createBNode()5415 PD_DocumentRDFMutation::createBNode()
5416 {
5417 PD_Document* doc = m_rdf->getDocument();
5418 std::stringstream ss;
5419 ss << "uri:bnode" << doc->getUID( UT_UniqueId::Annotation );
5420 return PD_URI( ss.str() );
5421 }
5422
5423 void
remove(const PD_RDFStatement & st)5424 PD_DocumentRDFMutation::remove( const PD_RDFStatement& st )
5425 {
5426 remove( st.getSubject(), st.getPredicate(), st.getObject() );
5427 }
5428
5429 void
remove(const std::list<PD_RDFStatement> & sl)5430 PD_DocumentRDFMutation::remove( const std::list< PD_RDFStatement >& sl )
5431 {
5432 for( std::list< PD_RDFStatement >::const_iterator si = sl.begin(); si!=sl.end(); ++si )
5433 {
5434 remove( *si );
5435 }
5436 }
5437
5438 void
remove(const PD_URI & s,const PD_URI & p)5439 PD_DocumentRDFMutation::remove( const PD_URI& s, const PD_URI& p )
5440 {
5441 PD_ObjectList objects = m_rdf->getObjects( s, p );
5442 std::list< PD_RDFStatement > removeList;
5443 for( PD_ObjectList::iterator it = objects.begin(); it != objects.end(); ++it )
5444 {
5445 PD_Object obj = *it;
5446 PD_RDFStatement st( s, p, obj );
5447 removeList.push_back( st );
5448 }
5449 remove( removeList );
5450 }
5451
5452
5453 int
add(PD_RDFModelHandle model)5454 PD_DocumentRDFMutation::add( PD_RDFModelHandle model )
5455 {
5456 int count = 0;
5457 PD_RDFModelIterator iter = model->begin();
5458 PD_RDFModelIterator e = model->end();
5459 for( ; iter != e; ++iter )
5460 {
5461 const PD_RDFStatement& st = *iter;
5462
5463 UT_DEBUGMSG(("PD_DocumentRDFMutation::add(submodel) ot:%d o:%s\n",
5464 st.getObject().getObjectType(), st.getObject().toString().c_str() ));
5465
5466 if( add( st ) )
5467 ++count;
5468 }
5469
5470 return count;
5471 }
5472
5473
5474 void
handleCollabEvent(gchar ** szAtts,gchar ** szProps)5475 PD_DocumentRDFMutation::handleCollabEvent( gchar** szAtts, gchar** szProps )
5476 {
5477 UT_DEBUGMSG(("PD_DocumentRDFMutation::handleCollabEvent (remote) rdf:%p\n", m_rdf));
5478 m_handlingAbiCollabNotification = true;
5479
5480 PP_AttrProp* addAP = new PP_AttrProp();
5481 PP_AttrProp* removeAP = new PP_AttrProp();
5482 addAP->setProperties( (const gchar**)szAtts );
5483 removeAP->setProperties( (const gchar**)szProps );
5484 handleAddAndRemove( addAP, removeAP );
5485 delete addAP;
5486 delete removeAP;
5487 }
5488
5489 /**
5490 * This is where the triples in @add and @remove will actually modify
5491 * the DocumentRDF. This method is called by commit() locally and by
5492 * handleCollabEvent to handle remote change notificatioans during
5493 * collaborative sessions.
5494 *
5495 * First the current AttrProp is copied from the DocumentRDF,
5496 * filtering out the triples from the remove table as the copy is
5497 * performed. Then the new triples are added and the
5498 * piecetable/documentRDF is updated to use the new RDF APIndex.
5499 */
5500 UT_Error
handleAddAndRemove(PP_AttrProp * add_,PP_AttrProp * remove_)5501 PD_DocumentRDFMutation::handleAddAndRemove( PP_AttrProp* add_, PP_AttrProp* remove_ )
5502 {
5503 // UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove (general) rdf:%p\n", m_rdf));
5504 // m_rdf->apDumpModel( remove_, "remove from model" );
5505 // m_rdf->apDumpModel( add_, "add to model" );
5506
5507
5508 /*
5509 * remove all the triples we don't want first
5510 * doing this set wise should great less junk AP instances.
5511 */
5512 const PP_AttrProp* existingAP = m_rdf->getAP();
5513 PP_AttrProp* newAP = new PP_AttrProp();
5514 size_t propCount = existingAP->getPropertyCount();
5515 for( size_t i = 0; i<propCount; ++i )
5516 {
5517 const gchar * szExistingName = 0;
5518 const gchar * szExistingValue = 0;
5519
5520 if( !existingAP->getNthProperty( i, szExistingName, szExistingValue))
5521 {
5522 UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove() failed to get prop:%ld\n", (long)i ));
5523 // failed to get old prop
5524 continue;
5525 }
5526
5527 const gchar* szPropertiesToRemove = 0;
5528 if( remove_->getProperty( szExistingName, szPropertiesToRemove ))
5529 {
5530 POCol existingProps = decodePOCol(szExistingValue);
5531 POCol removeProps = decodePOCol(szPropertiesToRemove);
5532 // UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove(1) n:%s exist.sz:%d rem.sz:%d\n",
5533 // szExistingName, existingProps.size(), removeProps.size() ));
5534 for( POCol::iterator iter = removeProps.begin(); iter != removeProps.end(); ++iter )
5535 {
5536 // UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove(rem) %s\n", iter->first.c_str() ));
5537 std::pair< POCol::iterator, POCol::iterator > range
5538 = std::equal_range( existingProps.begin(), existingProps.end(), iter->first );
5539 for( POCol::iterator t = range.first; t!=range.second; )
5540 {
5541 if( t->second == iter->second )
5542 {
5543 POCol::iterator target = t;
5544 t++;
5545 existingProps.erase( target );
5546 continue;
5547 }
5548 t++;
5549 }
5550 }
5551 std::string po = encodePOCol(existingProps);
5552 // commit() calls prune first, so this property
5553 // will disappear from the AP if it's list is empty
5554 if(existingProps.empty())
5555 po = "";
5556 // UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove(2) n:%s exist.sz:%d rem.sz:%d\n",
5557 // szExistingName, existingProps.size(), removeProps.size() ));
5558 if( !newAP->setProperty( szExistingName, po.c_str() ))
5559 {
5560 UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove() failed to set prop:%ld\n", (long)i ));
5561 // FIXME: failed to copy prop
5562 }
5563 }
5564 else
5565 {
5566 UT_DEBUGMSG(("PD_DocumentRDFMutation::handleAddAndRemove() copy prop:%s\n", szExistingName ));
5567 if( !newAP->setProperty( szExistingName, szExistingValue ))
5568 {
5569 // FIXME: failed to copy prop
5570 }
5571 }
5572 }
5573
5574 // m_rdf->apDumpModel( newAP, "model after remove..." );
5575
5576 // add all the new triples
5577 propCount = add_->getPropertyCount();
5578 for( size_t i = 0; i<propCount; ++i )
5579 {
5580 const gchar * szName = 0;
5581 const gchar * szValue = 0;
5582
5583 if( !add_->getNthProperty( i, szName, szValue))
5584 {
5585 // FIXME: failed to get old prop
5586 continue;
5587 }
5588 PD_URI s(szName);
5589 POCol c = decodePOCol(szValue);
5590 for( POCol::iterator iter = c.begin(); iter != c.end(); ++iter )
5591 {
5592 apAdd( newAP, s, iter->first, iter->second );
5593 }
5594 }
5595
5596 // m_rdf->apDumpModel( newAP, "updated RDF model..." );
5597 UT_Error e = m_rdf->setAP( newAP );
5598 if( e != UT_OK )
5599 {
5600 UT_DEBUGMSG(("DocumentRDFMutation::handleAddAndRemove() failed to add new AttrPropIndex for RDF update\n"));
5601 // MIQ 2010 July: addIfUniqueAP() method states false == memory error of some kind.
5602 return e;
5603 }
5604
5605 // m_rdf->apDumpModel( m_rdf->getAP(), "updated RDF model..." );
5606 return UT_OK;
5607 }
5608
5609
5610 /**
5611 * Commit the add() and remove() changes to the main document RDF.
5612 * This method also emits a change record detailing the update.
5613 *
5614 * Implementation: Note that at this stage we have m_crRemoveAP and
5615 * m_crAddAP which are the tripes to remove and add respectively.
5616 * These are also the triples that will be sent via abicollab to other
5617 * instances to add/remove so we might as well try to use the same
5618 * code to handle the mutation in both this and other abiword
5619 * instances.
5620 *
5621 * Note that you can only commit() once per PD_DocumentRDFMutation object.
5622 * So you should throw it away after a commit to avoid the temptation of
5623 * trying to add() more to it.
5624 */
commit()5625 UT_Error PD_DocumentRDFMutation::commit()
5626 {
5627 bool success = false;
5628
5629 UT_DEBUGMSG(("PD_DocumentRDF::commit(top1) this:%p rdf:%p\n", this, m_rdf));
5630 // UT_DEBUGMSG(("PD_DocumentRDF::commit(top2) m_rolledback:%d\n", m_rolledback));
5631 // UT_DEBUGMSG(("PD_DocumentRDF::commit(top3) rm.hasP:%d add.hasP:%d\n",
5632 // m_crRemoveAP->hasProperties(), m_crAddAP->hasProperties()));
5633 // if( m_crAddAP->hasProperties() )
5634 // {
5635 // UT_DEBUGMSG(("PD_DocumentRDF::commit(top3) add count:%d\n",
5636 // (int)m_crAddAP->getPropertyCount()));
5637 // }
5638 // m_rdf->apDumpModel( m_crAddAP, "xx add to model" );
5639
5640
5641 if(m_rolledback)
5642 return UT_OK;
5643 if( !m_crRemoveAP->hasProperties() && !m_crAddAP->hasProperties() )
5644 return UT_OK;
5645 if( m_handlingAbiCollabNotification )
5646 return UT_OK;
5647 if( m_committed )
5648 return UT_OK;
5649
5650 UT_DEBUGMSG(("PD_DocumentRDF::commit(running) rdf:%p\n", m_rdf));
5651 m_pAP->prune();
5652 m_pAP->markReadOnly();
5653 PD_Document* doc = m_rdf->getDocument();
5654 pt_PieceTable* pt = m_rdf->getPieceTable();
5655 pt_VarSet& m_varset = pt->getVarSet();
5656
5657 handleAddAndRemove( m_crAddAP, m_crRemoveAP );
5658 // UT_DEBUGMSG(("PD_DocumentRDF::commit(sending CR) rdf:%p\n", m_rdf));
5659
5660 if( !m_rdf->isStandAlone() )
5661 {
5662
5663 //
5664 // Notify others about this change...
5665 //
5666 PP_AttrProp* crAP = new PP_AttrProp();
5667 crAP->setAttributes( m_crAddAP->getProperties() );
5668 crAP->setProperties( m_crRemoveAP->getProperties() );
5669 crAP->markReadOnly();
5670
5671 PT_AttrPropIndex crAPI = 0;
5672 success = m_varset.addIfUniqueAP( crAP, &crAPI );
5673 // addIfUniqueAP() eats it
5674 crAP = 0;
5675
5676 if( !success )
5677 {
5678 UT_DEBUGMSG(("DocumentRDFMutation::commit() failed to add new AttrPropIndex for RDF update\n"));
5679 // MIQ 2010 July: addIfUniqueAP() method states false == memory error of some kind.
5680 return UT_OUTOFMEM;
5681 }
5682
5683 PT_DocPosition pos = 0;
5684 UT_uint32 iXID = 0;
5685 PX_ChangeRecord* pcr = new PX_ChangeRecord( PX_ChangeRecord::PXT_ChangeDocRDF,
5686 pos, crAPI, iXID );
5687 doc->notifyListeners( 0, pcr );
5688 delete pcr;
5689 // UT_DEBUGMSG(("PD_DocumentRDF::commit(done) rdf:%p\n", m_rdf));
5690 }
5691
5692 m_committed = true;
5693 m_rdf->maybeSetDocumentDirty();
5694 m_rdf->updateHaveSemItemsCache();
5695
5696 return UT_OK;
5697 }
5698
5699 /**
5700 * Forget the changes and do not automatically try to commit() them
5701 * when the PD_DocumentRDFMutation goes out of scope.
5702 */
rollback()5703 void PD_DocumentRDFMutation::rollback()
5704 {
5705 m_rolledback = true;
5706 }
5707
5708
5709