From 427f6b307aa35fc921aa8d8538b8c653219bb065 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Sun, 18 Apr 2010 19:03:21 +0100
Subject: Improve roster performance through map lookups on operations


diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp
index e6640e2..8c2aa0e 100644
--- a/Swiften/Roster/Roster.cpp
+++ b/Swiften/Roster/Roster.cpp
@@ -56,12 +56,14 @@ void Roster::handleUserAction(boost::shared_ptr<UserRosterAction> action) {
 void Roster::addContact(const JID& jid, const String& name, const String& group) {
 	ContactRosterItem *item = new ContactRosterItem(jid, name, getGroup(group), widgetFactory_);
 	items_.push_back(item);
+	itemMap_[jid.toBare()].push_back(item);
 	item->onUserAction.connect(boost::bind(&Roster::handleUserAction, this, _1));
 	filterItem(item);
 
 }
 
 void Roster::removeContact(const JID& jid) {
+	itemMap_.erase(jid.toBare());
 	std::vector<RosterItem*>::iterator it = children_.begin();
 	while (it != children_.end()) {
 		ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(*it);
@@ -91,6 +93,21 @@ void Roster::removeContactFromGroup(const JID& jid, const String& groupName) {
 
 
 void Roster::applyOnItems(const RosterItemOperation& operation) {
+	if (operation.requiresLookup()) {
+		applyOnItem(operation, operation.lookupJID());
+	} else {
+		applyOnAllItems(operation);
+	}
+}
+
+void Roster::applyOnItem(const RosterItemOperation& operation, const JID& jid) {
+	foreach (RosterItem* item, itemMap_[jid]) {
+		operation(item);
+		filterItem(item);
+	}
+}
+
+void Roster::applyOnAllItems(const RosterItemOperation& operation) {
 	std::deque<RosterItem*> queue(children_.begin(), children_.end());
 	while (!queue.empty()) {
 		RosterItem* item = *queue.begin();
diff --git a/Swiften/Roster/Roster.h b/Swiften/Roster/Roster.h
index 2e88c5d..5fc3cfb 100644
--- a/Swiften/Roster/Roster.h
+++ b/Swiften/Roster/Roster.h
@@ -14,6 +14,7 @@
 #include "Swiften/Roster/RosterFilter.h"
 
 #include <vector>
+#include <map>
 #include <boost/signal.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -35,6 +36,8 @@ class Roster {
 		void removeContact(const JID& jid);
 		void removeContactFromGroup(const JID& jid, const String& group);
 		void applyOnItems(const RosterItemOperation& operation);
+		void applyOnAllItems(const RosterItemOperation& operation);
+		void applyOnItem(const RosterItemOperation& operation, const JID& jid);
 		boost::signal<void (boost::shared_ptr<UserRosterAction>)> onUserAction;
 		void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();}
 		void removeFilter(RosterFilter *filter);
@@ -49,6 +52,7 @@ class Roster {
 		std::vector<RosterItem*> children_;
 		std::vector<RosterItem*> items_;
 		std::vector<RosterFilter*> filters_;
+		std::map<JID, std::vector<RosterItem*> > itemMap_;
 };
 }
 
diff --git a/Swiften/Roster/RosterItemOperation.h b/Swiften/Roster/RosterItemOperation.h
index a41ed6e..a901fb4 100644
--- a/Swiften/Roster/RosterItemOperation.h
+++ b/Swiften/Roster/RosterItemOperation.h
@@ -13,8 +13,14 @@ namespace Swift {
 
 class RosterItemOperation {
 	public:
-		virtual ~RosterItemOperation() {}
+		RosterItemOperation(bool requiresLookup = false, const JID& lookupJID = JID()) : requiresLookup_(requiresLookup), lookupJID_(lookupJID) {};
+		virtual ~RosterItemOperation() {};
+		bool requiresLookup() const {return requiresLookup_;};
+		const JID& lookupJID() const {return lookupJID_;}; 
 		virtual void operator() (RosterItem*) const = 0;
+	private:
+		bool requiresLookup_;
+		JID lookupJID_;
 };
 
 }
diff --git a/Swiften/Roster/SetAvatar.h b/Swiften/Roster/SetAvatar.h
index 3274d10..2b22188 100644
--- a/Swiften/Roster/SetAvatar.h
+++ b/Swiften/Roster/SetAvatar.h
@@ -18,7 +18,7 @@ class RosterItem;
 
 class SetAvatar : public RosterItemOperation {
 	public:
-		SetAvatar(const JID& jid, const String& path, JID::CompareType compareType = JID::WithoutResource) : jid_(jid), path_(path), compareType_(compareType) {
+		SetAvatar(const JID& jid, const String& path, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), jid_(jid), path_(path), compareType_(compareType) {
 		}
 
 		virtual void operator() (RosterItem* item) const {
diff --git a/Swiften/Roster/SetName.h b/Swiften/Roster/SetName.h
index 17bc2ea..33dd521 100644
--- a/Swiften/Roster/SetName.h
+++ b/Swiften/Roster/SetName.h
@@ -16,7 +16,7 @@ class RosterItem;
 
 class SetName : public RosterItemOperation {
 	public:
-		SetName(const String& name, const JID& jid, JID::CompareType compareType = JID::WithoutResource) : name_(name), jid_(jid), compareType_(compareType) {
+		SetName(const String& name, const JID& jid, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, jid), name_(name), jid_(jid), compareType_(compareType) {
 		}
 
 		virtual void operator() (RosterItem* item) const {
diff --git a/Swiften/Roster/SetPresence.h b/Swiften/Roster/SetPresence.h
index c4151bc..9cc3ba9 100644
--- a/Swiften/Roster/SetPresence.h
+++ b/Swiften/Roster/SetPresence.h
@@ -18,7 +18,7 @@ class RosterItem;
 
 class SetPresence : public RosterItemOperation {
 	public:
-		SetPresence(boost::shared_ptr<Presence> presence, JID::CompareType compareType = JID::WithoutResource) : presence_(presence), compareType_(compareType) {
+		SetPresence(boost::shared_ptr<Presence> presence, JID::CompareType compareType = JID::WithoutResource) : RosterItemOperation(true, presence->getFrom().toBare()), presence_(presence), compareType_(compareType) {
 		}
 
 		virtual void operator() (RosterItem* item) const {
-- 
cgit v0.10.2-6-g49f6