Code

Merge and cleanup of GSoC C++-ification project.
[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     _sm = sm;
59    init();
60 }
62 XMLNodeTracker::XMLNodeTracker() :
63                          _rootKey(DOCUMENT_ROOT_NODE),
64                          _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
65 {
66     _sm = NULL;
67     init();
68 }
70 XMLNodeTracker::~XMLNodeTracker()
71 {
72     _clear();
73 }
76 void
77 XMLNodeTracker::init()
78 {
79     _counter = 0;
81     // Construct special node maps
82     createSpecialNodeTables();
83     if (_sm)
84         reset();
85 }
87 void
88 XMLNodeTracker::setSessionManager(const SessionManager *val)
89 {
90     _sm = (SessionManager *)val;
91     if (_sm)
92         reset();
93 }
95 void 
96 XMLNodeTracker::put(const Glib::ustring &key, const XML::Node &nodeArg)
97 {
98     keyNodeTable.put(key, &nodeArg);
99 }
102 void
103 XMLNodeTracker::process(const KeyToNodeActionList &actions)
105     KeyToNodeActionList::const_iterator iter = actions.begin();
106     for(; iter != actions.end(); iter++) {
107         // Get the action to perform.
108         SerializedEventNodeAction action = *iter;
109         switch(action.second) {
110             case NODE_ADD:
111                 //g_log(NULL, G_LOG_LEVEL_DEBUG, 
112                 //"NODE_ADD event: key %s, node %p", 
113                 //action.first.first.c_str(), action.first.second);
114                 put(action.first.key, *action.first.node);
115                 break;
116             case NODE_REMOVE:
117                 //g_log(NULL, G_LOG_LEVEL_DEBUG,
118                 //"NODE_REMOVE event: key %s, node %p",
119                 // action.first.first.c_str(), action.first.second);
120                 //remove(const_cast< XML::Node& >(*action.first.second));
121                 break;
122             default:
123                 break;
124         }
125     }
128 XML::Node*
129 XMLNodeTracker::get(const Glib::ustring &key)
131     XML::Node *node = keyNodeTable.get(key);
132     if (node)
133         return node;
135     g_warning("Key %s is not being tracked!", key.c_str());
136     return NULL;
139 Glib::ustring
140 XMLNodeTracker::get(const XML::Node &nodeArg)
142     Glib::ustring key = keyNodeTable.get((XML::Node *)&nodeArg);
143     return key;
146 bool
147 XMLNodeTracker::isTracking(const Glib::ustring &key)
149     return (get(key)!=NULL);
152 bool
153 XMLNodeTracker::isTracking(const XML::Node &node)
155     return (get(node).size()>0);
159 bool
160 XMLNodeTracker::isRootNode(const XML::Node &node)
162     XML::Node* docroot = _sm->getDocument()->getReprRoot();
163     return (docroot == &node);
167 void
168 XMLNodeTracker::remove(const Glib::ustring& key)
170     g_log(NULL, G_LOG_LEVEL_DEBUG, "Removing node with key %s", key.c_str());
171     keyNodeTable.remove(key);
174 void
175 XMLNodeTracker::remove(const XML::Node &nodeArg)
177     //g_log(NULL, G_LOG_LEVEL_DEBUG, "Removing node %p", &node);
178     keyNodeTable.remove((XML::Node *)&nodeArg);
182 bool 
183 XMLNodeTracker::isSpecialNode(const Glib::ustring &name)
185     return (_specialnodes.find(name.data()) != _specialnodes.end());
188 Glib::ustring
189 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const& name)
191     return _specialnodes[name.data()];
194 Glib::ustring
195 XMLNodeTracker::generateKey(gchar const* JID)
197     return String::compose("%1;%2", _counter++, JID);
200 Glib::ustring 
201 XMLNodeTracker::generateKey()
203     std::bitset< NUM_FLAGS >& status = _sm->getStatus();
204     Glib::ustring ret;
205     if (status[IN_CHATROOM]) {
206         // This is not strictly required for chatrooms: chatrooms will
207         // function just fine with the user-to-user ID scheme.  However,
208         // the user-to-user scheme can lead to loss of anonymity
209         // in anonymous chat rooms, since it contains the real JID
210         // of a user.
211         /*
212         ret = String::compose("%1;%2@%3/%4",
213                  _counter++,
214                  _sm->getClient().getUsername(),
215                  _sm->getClient().getHost(),
216                  sd->chat_handle);
217        */
218        //We need to work on this since Pedro allows multiple chatrooms
219         ret = String::compose("%1;%2",
220                  _counter++, 
221                  _sm->getClient().getJid());
222     } else {
223         ret = String::compose("%1;%2",
224                  _counter++, 
225                  _sm->getClient().getJid());
226     }
227     return  ret;
230 void
231 XMLNodeTracker::createSpecialNodeTables()
233     int const sz = sizeof(specialnodekeys) / sizeof(char const*);
234     for(int i = 0; i < sz; i++)
235          _specialnodes[specialnodenames[i]] = specialnodekeys[i];
239 // rather nasty and crufty debugging function
240 void 
241 XMLNodeTracker::dump()
243     g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker dump for %s",
244            _sm->getClient().getJid().c_str());
248     g_log(NULL, G_LOG_LEVEL_DEBUG, "%u entries in keyNodeTable", 
249                          keyNodeTable.size());
251     g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker keyNodeTable dump");
252     for (unsigned int i=0 ; i<keyNodeTable.size() ; i++)
253         {
254         KeyNodePair pair = keyNodeTable.item(i);
255         Glib::ustring key = pair.key;
256         XML::Node *node = pair.node;
257         char *name    = "none";
258         char *content = "none";
259         if (node)
260             {
261             name = (char *)node->name();
262             content = (char *)node->content();
263             }
264         g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%p (%s) (%s)",
265                   key.c_str(), node, name, content);
266         }
268     g_log(NULL, G_LOG_LEVEL_DEBUG, "_specialnodes dump");
269     std::map< char const*, char const* >::iterator k = _specialnodes.begin();
270     while(k != _specialnodes.end()) {
271             g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%s", (*k).first, (*k).second);
272             k++;
273     }
276 void XMLNodeTracker::reset()
278     _clear();
280     // Find and insert special nodes
281     // root node
282     put(_rootKey, *(_sm->getDocument()->getReprRoot()));
284     // namedview node
285     SPObject* namedview = sp_item_group_get_child_by_name(
286                  (SPGroup *)_sm->getDocument()->root,
287                   NULL, DOCUMENT_NAMEDVIEW_NAME);
288     if (!namedview) {
289         g_warning("namedview node does not exist; it will be created during synchronization");
290     } else {
291         put(_namedviewKey, *(SP_OBJECT_REPR(namedview)));
292     }
295 void
296 XMLNodeTracker::_clear()
298     // Remove all keys in both trackers, and delete each key.
299     keyNodeTable.clear();
302 }  // namespace Whiteboard
304 }  // namespace Inkscape
308 /*
309   Local Variables:
310   mode:c++
311   c-file-style:"stroustrup"
312   c-file-offsets:((innamespace . 0)(inline-open . 0))
313   indent-tabs-mode:nil
314   fill-column:99
315   End:
316 */
317 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :