Code

replace Util::SharedCStringPtr with the more general Util::shared_ptr<>
[inkscape.git] / src / jabber_whiteboard / node-tracker.cpp
1 /**
2  * Whiteboard session manager
3  * XML node tracking facility
4  *
5  * Authors:
6  * David Yip <yipdw@rose-hulman.edu>
7  *
8  * Copyright (c) 2005 Authors
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #include "sp-object.h"
14 #include "sp-item-group.h"
15 #include "document.h"
16 #include "document-private.h"
18 #include "xml/node.h"
20 #include "util/compose.hpp"
22 #include "jabber_whiteboard/session-manager.h"
23 #include "jabber_whiteboard/node-tracker.h"
26 // TODO: remove redundant calls to isTracking(); it's a rather unnecessary
27 // performance burden. 
28 namespace Inkscape {
30 namespace Whiteboard {
32 // Lookup tables
34 /**
35  * Keys for special nodes.
36  *
37  * A special node is a node that can only appear once in a document.
38  */
39 char const* specialnodekeys[] = {
40         DOCUMENT_ROOT_NODE,
41         DOCUMENT_NAMEDVIEW_NODE,
42 };
44 /**
45  * Names of special nodes.
46  *
47  * A special node is a node that can only appear once in a document.
48  */
49 char const* specialnodenames[] = {
50         DOCUMENT_ROOT_NAME,
51         DOCUMENT_NAMEDVIEW_NAME,
52 };
54 XMLNodeTracker::XMLNodeTracker(SessionManager* sm) :
55         _rootKey(DOCUMENT_ROOT_NODE),
56         _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
57 {
58         this->_sm = sm;
59         this->_counter = 0;
61         // Construct special node maps
62         this->createSpecialNodeTables();
63         this->reset();
64 }
66 XMLNodeTracker::~XMLNodeTracker()
67 {
68         this->_clear();
69 }
71 void
72 XMLNodeTracker::put(std::string key, XML::Node const& node)
73 {
74         this->put(key, const_cast< XML::Node& >(node));
75 }
77 void 
78 XMLNodeTracker::put(std::string key, XML::Node& node)
79 {       
80         KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
81         if (i != this->_keyToNode.end()) {
82                 this->_keyToNode.erase(i);
83         }
84         this->_keyToNode.insert(std::make_pair< std::string, XML::Node* >(key, &node));
86         TrackerNodeToKeyMap::iterator j = this->_nodeToKey.find(&node);
87         if (j != this->_nodeToKey.end()) {
88                 this->_nodeToKey.erase(j);
89         }
90         this->_nodeToKey.insert(std::make_pair< XML::Node*, std::string >(&node, key));
91 }
93 void
94 XMLNodeTracker::put(KeyToNodeMap& newids, NodeToKeyMap& newnodes)
95 {
96         // TODO: redo
97         KeyToNodeMap::iterator i = newids.begin();
99         for(; i != newids.end(); i++) {
100                 this->put((*i).first, *((*i).second));
101         }
104 void
105 XMLNodeTracker::process(KeyToNodeActionList& actions)
107         KeyToNodeActionList::iterator i = actions.begin();
108         for(; i != actions.end(); i++) {
109                 // Get the action to perform.
110                 SerializedEventNodeAction action = *i;
111                 switch(action.second) {
112                         case NODE_ADD:
113                                 this->put(action.first.first, *action.first.second);
114                                 break;
115                         case NODE_REMOVE:
116                 //              this->remove(const_cast< XML::Node& >(*action.first.second));
117                                 break;
118                         default:
119                                 break;
120                 }
121         }
124 XML::Node*
125 XMLNodeTracker::get(std::string& key)
127         KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
128         if (i != this->_keyToNode.end()) {
129                 return (*i).second;
130         } else {
131                 g_warning("Key %s is not being tracked!", key.c_str());
132                 return NULL;
133         }
136 XML::Node*
137 XMLNodeTracker::get(std::string const& key)
139         return this->get(const_cast< std::string& >(key));
143 std::string const
144 XMLNodeTracker::get(XML::Node& node)
146         TrackerNodeToKeyMap::iterator i = this->_nodeToKey.find(&node);
147         if (i != this->_nodeToKey.end()) {
148                 return (*i).second;
149         } else {
150                 return "";
151         }
154 std::string const
155 XMLNodeTracker::get(XML::Node const& node)
157         return this->get(const_cast< XML::Node& >(node));
160 bool
161 XMLNodeTracker::isTracking(std::string& key)
163         return (this->_keyToNode.find(key) != this->_keyToNode.end());
166 bool
167 XMLNodeTracker::isTracking(std::string const& key)
169         return this->isTracking(const_cast< std::string& >(key));
172 bool
173 XMLNodeTracker::isTracking(XML::Node& node)
175         return (this->_nodeToKey.find(&node) != this->_nodeToKey.end());
178 bool
179 XMLNodeTracker::isTracking(XML::Node const& node)
181         return this->isTracking(const_cast< XML::Node& >(node));
184 bool
185 XMLNodeTracker::isRootNode(XML::Node& node)
187         XML::Node* docroot = sp_document_repr_root(this->_sm->document());
188         return (docroot == &node);
192 void
193 XMLNodeTracker::remove(std::string& key)
195         if (this->isTracking(key)) {
196                 XML::Node* element = this->get(key);
197                 this->_keyToNode.erase(key);
198                 this->_nodeToKey.erase(element);
199         } 
202 void
203 XMLNodeTracker::remove(XML::Node& node)
205         if (this->isTracking(node)) {
206                 std::string const element = this->get(node);
207                 this->_nodeToKey.erase(&node);
208                 this->_keyToNode.erase(element);
209         }
212 bool 
213 XMLNodeTracker::isSpecialNode(char const* name)
215         return (this->_specialnodes.find(name) != this->_specialnodes.end());   
218 bool 
219 XMLNodeTracker::isSpecialNode(std::string const& name)
221         return (this->_specialnodes.find(name.data()) != this->_specialnodes.end());    
224 std::string const
225 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const& name)
227         return this->_specialnodes[name.data()];
230 std::string const
231 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const* name)
233         return this->_specialnodes[name->data()];       
236 std::string
237 XMLNodeTracker::generateKey(gchar const* JID)
239         return String::compose("%1;%2", this->_counter++, JID);
242 std::string 
243 XMLNodeTracker::generateKey()
245         SessionData* sd = this->_sm->session_data;
246         std::bitset< NUM_FLAGS >& status = sd->status;
247         if (status[IN_CHATROOM]) {
248                 // This is not strictly required for chatrooms: chatrooms will
249                 // function just fine with the user-to-user ID scheme.  However,
250                 // the user-to-user scheme can lead to loss of anonymity
251                 // in anonymous chat rooms, since it contains the real JID
252                 // of a user.
253                 return String::compose("%1;%2@%3/%4", this->_counter++, sd->chat_name, sd->chat_server, sd->chat_handle);
254         } else {
255                 return String::compose("%1;%2", this->_counter++, lm_connection_get_jid(sd->connection));
256         }
259 void
260 XMLNodeTracker::createSpecialNodeTables()
262         int const sz = sizeof(specialnodekeys) / sizeof(char const*);
263         for(int i = 0; i < sz; i++) {
264                 this->_specialnodes[specialnodenames[i]] = specialnodekeys[i];
265         }
269 // rather nasty and crufty debugging function
270 void 
271 XMLNodeTracker::dump()
273         g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker dump for %s", lm_connection_get_jid(this->_sm->session_data->connection));
274         KeyToTrackerNodeMap::iterator i = this->_keyToNode.begin();
275         TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
276         std::map< char const*, char const* >::iterator k = this->_specialnodes.begin();
277         
279         g_log(NULL, G_LOG_LEVEL_DEBUG, "%u entries in keyToNode, %u entries in nodeToKey", this->_keyToNode.size(), this->_nodeToKey.size());
281         if (this->_keyToNode.size() != this->_nodeToKey.size()) {
282                 g_warning("Map sizes do not match!");
283         }
285         g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker keyToNode dump");
286         while(i != this->_keyToNode.end()) {
287                 if (!((*i).first.empty())) {
288                         if ((*i).second != NULL) {
289                                 g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%p (%s) (%s)", (*i).first.c_str(), (*i).second, (*i).second->name(), (*i).second->content());
290                         } else {
291                                 g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t(null)", (*i).first.c_str());
292                         }
293                 } else {
294                         g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%p (%s)", (*i).second, (*i).second->name());
295                 }
296                 i++;
297         }
299         g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker nodeToKey dump");
300         while(j != this->_nodeToKey.end()) {
301                 if (!((*j).second.empty())) {
302                         if ((*j).first) {
303                                 g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t%s (parent %p)", (*j).first, (*j).second.c_str(), (*j).first->parent());
304                         } else {
305                                 g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%s", (*j).second.c_str());
306                         }
307                 } else {
308                         g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t(null)", (*j).first);
309                 }
310                 j++;
311         }
313         g_log(NULL, G_LOG_LEVEL_DEBUG, "_specialnodes dump");
314         while(k != this->_specialnodes.end()) {
315                 g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%s", (*k).first, (*k).second);
316                 k++;
317         }
320 void
321 XMLNodeTracker::reset()
323         this->_clear();
325         // Find and insert special nodes
326         // root node
327         this->put(this->_rootKey, *(sp_document_repr_root(this->_sm->document())));
329         // namedview node
330         SPObject* namedview = sp_item_group_get_child_by_name((SPGroup *)this->_sm->document()->root, NULL, DOCUMENT_NAMEDVIEW_NAME);
331         if (!namedview) {
332                 g_warning("namedview node does not exist; it will be created during synchronization");
333         } else {
334                 this->put(this->_namedviewKey, *(SP_OBJECT_REPR(namedview)));
335         }
338 void
339 XMLNodeTracker::_clear()
341         // Remove all keys in both trackers, and delete each key.
342         this->_keyToNode.clear();
343         this->_nodeToKey.clear();
345         /*
346         TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
347         for(; j != this->_nodeToKey.end(); j++) {
348                 this->_nodeToKey.erase(j);
349         }
350         */
359 /*
360   Local Variables:
361   mode:c++
362   c-file-style:"stroustrup"
363   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
364   indent-tabs-mode:nil
365   fill-column:99
366   End:
367 */
368 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :