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