Logo Search packages:      
Sourcecode: inkscape version File versions  Download package

node-tracker.cpp

/**
 * Whiteboard session manager
 * XML node tracking facility
 *
 * Authors:
 * David Yip <yipdw@rose-hulman.edu>
 *
 * Copyright (c) 2005 Authors
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include "sp-object.h"
#include "sp-item-group.h"
#include "document.h"
#include "document-private.h"

#include "xml/node.h"

#include "util/compose.hpp"

#include "jabber_whiteboard/session-manager.h"
#include "jabber_whiteboard/node-tracker.h"


// TODO: remove redundant calls to isTracking(); it's a rather unnecessary
// performance burden. 
namespace Inkscape {

namespace Whiteboard {

// Lookup tables

/**
 * Keys for special nodes.
 *
 * A special node is a node that can only appear once in a document.
 */
char const* specialnodekeys[] = {
      DOCUMENT_ROOT_NODE,
      DOCUMENT_NAMEDVIEW_NODE,
};

/**
 * Names of special nodes.
 *
 * A special node is a node that can only appear once in a document.
 */
char const* specialnodenames[] = {
      DOCUMENT_ROOT_NAME,
      DOCUMENT_NAMEDVIEW_NAME,
};

00054 XMLNodeTracker::XMLNodeTracker(SessionManager* sm) :
      _rootKey(DOCUMENT_ROOT_NODE),
      _namedviewKey(DOCUMENT_NAMEDVIEW_NODE)
{
      this->_sm = sm;
      this->_counter = 0;

      // Construct special node maps
      this->createSpecialNodeTables();
      this->reset();
}

XMLNodeTracker::~XMLNodeTracker()
{
      this->_clear();
}

void
00072 XMLNodeTracker::put(std::string key, XML::Node const& node)
{
      this->put(key, const_cast< XML::Node& >(node));
}

void 
00078 XMLNodeTracker::put(std::string key, XML::Node& node)
{     
      KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
      if (i != this->_keyToNode.end()) {
            this->_keyToNode.erase(i);
      }
      this->_keyToNode.insert(std::make_pair< std::string, XML::Node* >(key, &node));

      TrackerNodeToKeyMap::iterator j = this->_nodeToKey.find(&node);
      if (j != this->_nodeToKey.end()) {
            this->_nodeToKey.erase(j);
      }
      this->_nodeToKey.insert(std::make_pair< XML::Node*, std::string >(&node, key));
}

void
00094 XMLNodeTracker::put(KeyToNodeMap& newids, NodeToKeyMap& newnodes)
{
      // TODO: redo
      KeyToNodeMap::iterator i = newids.begin();

      for(; i != newids.end(); i++) {
            this->put((*i).first, *((*i).second));
      }
}

void
00105 XMLNodeTracker::process(KeyToNodeActionList& actions)
{
      KeyToNodeActionList::iterator i = actions.begin();
      for(; i != actions.end(); i++) {
            // Get the action to perform.
            SerializedEventNodeAction action = *i;
            switch(action.second) {
                  case NODE_ADD:
                        this->put(action.first.first, *action.first.second);
                        break;
                  case NODE_REMOVE:
            //          this->remove(const_cast< XML::Node& >(*action.first.second));
                        break;
                  default:
                        break;
            }
      }
}

XML::Node*
00125 XMLNodeTracker::get(std::string& key)
{
      KeyToTrackerNodeMap::iterator i = this->_keyToNode.find(key);
      if (i != this->_keyToNode.end()) {
            return (*i).second;
      } else {
            g_warning("Key %s is not being tracked!", key.c_str());
            return NULL;
      }
}

XML::Node*
00137 XMLNodeTracker::get(std::string const& key)
{
      return this->get(const_cast< std::string& >(key));
}


std::string const
00144 XMLNodeTracker::get(XML::Node& node)
{
      TrackerNodeToKeyMap::iterator i = this->_nodeToKey.find(&node);
      if (i != this->_nodeToKey.end()) {
            return (*i).second;
      } else {
            return "";
      }
}

std::string const
00155 XMLNodeTracker::get(XML::Node const& node)
{
      return this->get(const_cast< XML::Node& >(node));
}

bool
00161 XMLNodeTracker::isTracking(std::string& key)
{
      return (this->_keyToNode.find(key) != this->_keyToNode.end());
}

bool
00167 XMLNodeTracker::isTracking(std::string const& key)
{
      return this->isTracking(const_cast< std::string& >(key));
}

bool
00173 XMLNodeTracker::isTracking(XML::Node& node)
{
      return (this->_nodeToKey.find(&node) != this->_nodeToKey.end());
}

bool
00179 XMLNodeTracker::isTracking(XML::Node const& node)
{
      return this->isTracking(const_cast< XML::Node& >(node));
}

bool
00185 XMLNodeTracker::isRootNode(XML::Node& node)
{
      XML::Node* docroot = sp_document_repr_root(this->_sm->document());
      return (docroot == &node);
}


void
00193 XMLNodeTracker::remove(std::string& key)
{
      if (this->isTracking(key)) {
            XML::Node* element = this->get(key);
            this->_keyToNode.erase(key);
            this->_nodeToKey.erase(element);
      } 
}

void
00203 XMLNodeTracker::remove(XML::Node& node)
{
      if (this->isTracking(node)) {
            std::string const element = this->get(node);
            this->_nodeToKey.erase(&node);
            this->_keyToNode.erase(element);
      }
}

bool 
00213 XMLNodeTracker::isSpecialNode(char const* name)
{
      return (this->_specialnodes.find(name) != this->_specialnodes.end());   
}

bool 
00219 XMLNodeTracker::isSpecialNode(std::string const& name)
{
      return (this->_specialnodes.find(name.data()) != this->_specialnodes.end());  
}

std::string const
00225 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const& name)
{
      return this->_specialnodes[name.data()];
}

std::string const
00231 XMLNodeTracker::getSpecialNodeKeyFromName(Glib::ustring const* name)
{
      return this->_specialnodes[name->data()]; 
}

std::string
00237 XMLNodeTracker::generateKey(gchar const* JID)
{
      return String::compose("%1;%2", this->_counter++, JID);
}

std::string 
00243 XMLNodeTracker::generateKey()
{
      SessionData* sd = this->_sm->session_data;
      std::bitset< NUM_FLAGS >& status = sd->status;
      if (status[IN_CHATROOM]) {
            // This is not strictly required for chatrooms: chatrooms will
            // function just fine with the user-to-user ID scheme.  However,
            // the user-to-user scheme can lead to loss of anonymity
            // in anonymous chat rooms, since it contains the real JID
            // of a user.
            return String::compose("%1;%2@%3/%4", this->_counter++, sd->chat_name, sd->chat_server, sd->chat_handle);
      } else {
            return String::compose("%1;%2", this->_counter++, lm_connection_get_jid(sd->connection));
      }
}

void
XMLNodeTracker::createSpecialNodeTables()
{
      int const sz = sizeof(specialnodekeys) / sizeof(char const*);
      for(int i = 0; i < sz; i++) {
            this->_specialnodes[specialnodenames[i]] = specialnodekeys[i];
      }
}


// rather nasty and crufty debugging function
void 
XMLNodeTracker::dump()
{
      g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker dump for %s", lm_connection_get_jid(this->_sm->session_data->connection));
      KeyToTrackerNodeMap::iterator i = this->_keyToNode.begin();
      TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
      std::map< char const*, char const* >::iterator k = this->_specialnodes.begin();
      

      g_log(NULL, G_LOG_LEVEL_DEBUG, "%u entries in keyToNode, %u entries in nodeToKey", this->_keyToNode.size(), this->_nodeToKey.size());

      if (this->_keyToNode.size() != this->_nodeToKey.size()) {
            g_warning("Map sizes do not match!");
      }

      g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker keyToNode dump");
      while(i != this->_keyToNode.end()) {
            if (!((*i).first.empty())) {
                  if ((*i).second != NULL) {
                        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());
                  } else {
                        g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t(null)", (*i).first.c_str());
                  }
            } else {
                  g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%p (%s)", (*i).second, (*i).second->name());
            }
            i++;
      }

      g_log(NULL, G_LOG_LEVEL_DEBUG, "XMLNodeTracker nodeToKey dump");
      while(j != this->_nodeToKey.end()) {
            if (!((*j).second.empty())) {
                  if ((*j).first) {
                        g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t%s (parent %p)", (*j).first, (*j).second.c_str(), (*j).first->parent());
                  } else {
                        g_log(NULL, G_LOG_LEVEL_DEBUG, "(null)\t->\t%s", (*j).second.c_str());
                  }
            } else {
                  g_log(NULL, G_LOG_LEVEL_DEBUG, "%p\t->\t(null)", (*j).first);
            }
            j++;
      }

      g_log(NULL, G_LOG_LEVEL_DEBUG, "_specialnodes dump");
      while(k != this->_specialnodes.end()) {
            g_log(NULL, G_LOG_LEVEL_DEBUG, "%s\t->\t%s", (*k).first, (*k).second);
            k++;
      }
}

void
XMLNodeTracker::reset()
{
      this->_clear();

      // Find and insert special nodes
      // root node
      this->put(this->_rootKey, *(sp_document_repr_root(this->_sm->document())));

      // namedview node
      SPObject* namedview = sp_item_group_get_child_by_name((SPGroup *)this->_sm->document()->root, NULL, DOCUMENT_NAMEDVIEW_NAME);
      if (!namedview) {
            g_warning("namedview node does not exist; it will be created during synchronization");
      } else {
            this->put(this->_namedviewKey, *(SP_OBJECT_REPR(namedview)));
      }
}

void
XMLNodeTracker::_clear()
{
      // Remove all keys in both trackers, and delete each key.
      this->_keyToNode.clear();
      this->_nodeToKey.clear();

      /*
      TrackerNodeToKeyMap::iterator j = this->_nodeToKey.begin();
      for(; j != this->_nodeToKey.end(); j++) {
            this->_nodeToKey.erase(j);
      }
      */
}

}

}



/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :

Generated by  Doxygen 1.6.0   Back to index