From b63574ca72ccf0ae197f35e2000ad0c6973b2505 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 24 Oct 2010 17:44:12 +0200
Subject: Moving more from Swift to Client.


diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 10a0336..f465ef1 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -17,7 +17,7 @@
 #include "Swiften/Disco/EntityCapsManager.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindow.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swift/Controllers/XMPPEvents/EventController.h"
 
 namespace Swift {
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 9f38bb8..44fbcfe 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -24,7 +24,7 @@
 #include "Swiften/Avatars/AvatarMemoryStorage.h"
 #include "Swiften/VCards/VCardManager.h"
 #include "Swiften/VCards/VCardMemoryStorage.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swiften/Roster/XMPPRosterImpl.h"
 #include "Swift/Controllers/UnitTest/MockChatWindow.h"
 #include "Swiften/Client/DummyStanzaChannel.h"
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index 19e5c36..ea5a705 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -14,7 +14,7 @@
 #include "Swift/Controllers/Chat/MUCController.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindow.h"
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swiften/Roster/XMPPRoster.h"
 #include "Swift/Controllers/UIEvents/UIEventStream.h"
 #include "Swift/Controllers/UnitTest/MockChatWindow.h"
diff --git a/Swift/Controllers/EventNotifier.cpp b/Swift/Controllers/EventNotifier.cpp
index 605c13b..e08c8ed 100644
--- a/Swift/Controllers/EventNotifier.cpp
+++ b/Swift/Controllers/EventNotifier.cpp
@@ -11,7 +11,7 @@
 #include "Swift/Controllers/XMPPEvents/EventController.h"
 #include "SwifTools/Notifier/Notifier.h"
 #include "Swiften/Avatars/AvatarManager.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swiften/JID/JID.h"
 #include "Swift/Controllers/XMPPEvents/MessageEvent.h"
 #include "Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h"
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index a2d8331..c69aa00 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -27,7 +27,7 @@
 #include "Swift/Controllers/UIInterfaces/LoginWindowFactory.h"
 #include "Swift/Controllers/UIInterfaces/MainWindow.h"
 #include "Swift/Controllers/Chat/MUCController.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swift/Controllers/RosterController.h"
 #include "Swift/Controllers/SoundEventController.h"
 #include "Swift/Controllers/SoundPlayer.h"
@@ -53,9 +53,6 @@
 #include "Swiften/Disco/CapsInfoGenerator.h"
 #include "Swiften/Disco/GetDiscoInfoRequest.h"
 #include "Swiften/VCards/GetVCardRequest.h"
-#include "Swiften/Avatars/AvatarManagerImpl.h"
-#include "Swiften/Disco/CapsManager.h"
-#include "Swiften/Disco/EntityCapsManager.h"
 #include "Swiften/StringCodecs/SHA1.h"
 #include "Swiften/StringCodecs/Hexify.h"
 #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
@@ -98,12 +95,8 @@ MainController::MainController(
 	storages_ = NULL;
 	statusTracker_ = NULL;
 	client_ = NULL;
-	avatarManager_ = NULL;
-	capsManager_ = NULL;
-	entityCapsManager_ = NULL;
 	presenceNotifier_ = NULL;
 	eventNotifier_ = NULL;
-	nickResolver_ = NULL;
 	rosterController_ = NULL;
 	chatsManager_ = NULL;
 	eventWindowController_ = NULL;
@@ -196,14 +189,6 @@ void MainController::resetClient() {
 	eventNotifier_ = NULL;
 	delete presenceNotifier_;
 	presenceNotifier_ = NULL;
-	delete entityCapsManager_;
-	entityCapsManager_ = NULL;
-	delete capsManager_;
-	capsManager_ = NULL;
-	delete avatarManager_;
-	avatarManager_ = NULL;
-	delete nickResolver_;
-	nickResolver_ = NULL;
 	delete client_;
 	client_ = NULL;
 	delete storages_;
@@ -247,13 +232,13 @@ void MainController::handleConnected() {
 	bool freshLogin = rosterController_ == NULL;
 	myStatusLooksOnline_ = true;
 	if (freshLogin) {
-		rosterController_ = new RosterController(jid_, client_->getRoster(), avatarManager_, mainWindowFactory_, nickResolver_, client_->getPresenceOracle(), client_->getPresenceSender(), eventController_, uiEventStream_, client_->getIQRouter(), settings_);
+		rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), mainWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), eventController_, uiEventStream_, client_->getIQRouter(), settings_);
 		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
 		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
 
-		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, nickResolver_, client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, client_->getMUCRegistry(), entityCapsManager_);
+		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, client_->getMUCRegistry(), client_->getEntityCapsManager());
 		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
-		chatsManager_->setAvatarManager(avatarManager_);
+		chatsManager_->setAvatarManager(client_->getAvatarManager());
 
 		eventWindowController_ = new EventWindowController(eventController_, eventWindowFactory_);
 
@@ -391,13 +376,9 @@ void MainController::performLoginFromCachedCredentials() {
 		client_->setSoftwareVersion(CLIENT_NAME, buildVersion);
 
 		client_->getVCardManager()->onVCardChanged.connect(boost::bind(&MainController::handleVCardReceived, this, _1, _2));
-		nickResolver_ = new NickResolver(this->jid_.toBare(), client_->getRoster(), client_->getVCardManager(), client_->getMUCRegistry());
-		avatarManager_ = new AvatarManagerImpl(client_->getVCardManager(), client_->getStanzaChannel(), storages_->getAvatarStorage(), client_->getMUCRegistry());
-		capsManager_ = new CapsManager(storages_->getCapsStorage(), client_->getStanzaChannel(), client_->getIQRouter());
-		entityCapsManager_ = new EntityCapsManager(capsManager_, client_->getStanzaChannel());
-		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), avatarManager_, nickResolver_, client_->getPresenceOracle(), &timerFactory_);
+		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), client_->getAvatarManager(), client_->getNickResolver(), client_->getPresenceOracle(), &timerFactory_);
 		presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
-		eventNotifier_ = new EventNotifier(eventController_, notifier_, avatarManager_, nickResolver_);
+		eventNotifier_ = new EventNotifier(eventController_, notifier_, client_->getAvatarManager(), client_->getNickResolver());
 		eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
 		if (!certificateFile_.isEmpty()) {
 			client_->setCertificate(certificateFile_);
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 0a14993..22d2559 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -28,7 +28,6 @@
 #include "Swift/Controllers/UIEvents/UIEvent.h"
 
 namespace Swift {
-	class Application;
 	class Client;
 	class ChatWindowFactory;
 	class ChatController;
@@ -37,12 +36,8 @@ namespace Swift {
 	class EventController;
 	class MainWindowFactory;
 	class MainWindow;
-	class NickResolver;
 	class RosterController;
 	class DiscoInfoResponder;
-	class AvatarManager;
-	class CapsManager;
-	class EntityCapsManager;
 	class LoginWindow;
 	class EventLoop;
 	class LoginWindowFactory;
@@ -133,7 +128,6 @@ namespace Swift {
 			EventController* eventController_;
 			EventWindowController* eventWindowController_;
 			LoginWindow* loginWindow_;
-			NickResolver* nickResolver_;
 			DiscoInfoResponder* discoResponder_;
 			UIEventStream* uiEventStream_;
 			XMLConsoleController* xmlConsoleController_;
@@ -143,9 +137,6 @@ namespace Swift {
 			JID boundJID_;
 			SystemTrayController* systemTrayController_;
 			SoundEventController* soundEventController_;
-			AvatarManager* avatarManager_;
-			CapsManager* capsManager_;
-			EntityCapsManager* entityCapsManager_;
 			String vCardPhotoHash_;
 			String password_;
 			String certificateFile_;
diff --git a/Swift/Controllers/NickResolver.cpp b/Swift/Controllers/NickResolver.cpp
deleted file mode 100644
index 2cc6562..0000000
--- a/Swift/Controllers/NickResolver.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include "Swift/Controllers/NickResolver.h"
-
-#include <boost/shared_ptr.hpp>
-#include <boost/bind.hpp>
-
-#include "Swiften/MUC/MUCRegistry.h"
-#include "Swiften/Roster/XMPPRoster.h"
-#include "Swiften/VCards/VCardManager.h"
-
-// FIXME: The NickResolver currently relies on the vcard being requested by the client on login.
-// The VCardManager should get an onConnected() signal (which is signalled when the stanzachannel is available(, and each time this is emitted,
-// the nickresolver should request the vcard.
-
-namespace Swift {
-
-NickResolver::NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry) : ownJID_(ownJID) {
-	xmppRoster_ = xmppRoster;
-	vcardManager_ = vcardManager;
-	if (vcardManager_) {
-		vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2));
-	}
-	mucRegistry_ = mucRegistry;
-}
-
-String NickResolver::jidToNick(const JID& jid) {
-	if (jid.toBare() == ownJID_) {
-		if (!ownNick_.isEmpty()) {
-			return ownNick_;
-		}
-	}
-	String nick;
-
-	if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) {
-		return jid.getResource().isEmpty() ? jid.toBare().toString() : jid.getResource();
-	}
-
-	if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).isEmpty()) {
-		return xmppRoster_->getNameForJID(jid);
-	}
-
-	return jid.toBare();
-}
-
-void NickResolver::handleVCardReceived(const JID& jid, VCard::ref ownVCard) {
-	if (!jid.equals(ownJID_, JID::WithoutResource)) {
-		return;
-	}
-	String initialNick = ownNick_;
-	ownNick_ = ownJID_.toString();
-	if (ownVCard) {
-		if (!ownVCard->getNickname().isEmpty()) {
-			ownNick_ = ownVCard->getNickname();
-		} else if (!ownVCard->getGivenName().isEmpty()) {
-			ownNick_ = ownVCard->getGivenName();
-		} else if (!ownVCard->getFullName().isEmpty()) {
-			ownNick_ = ownVCard->getFullName();
-		}
-	}
-	if (ownNick_ != initialNick) {
-		onOwnNickChanged(ownNick_);
-	}
-}
-
-}
-
diff --git a/Swift/Controllers/NickResolver.h b/Swift/Controllers/NickResolver.h
deleted file mode 100644
index 7f00acd..0000000
--- a/Swift/Controllers/NickResolver.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <map>
-#include <boost/signals.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include "Swiften/Base/String.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/VCard.h"
-
-namespace Swift {
-	class XMPPRoster;
-	class MUCRegistry;
-	class VCardManager;
-	class NickResolver {
-		public:
-			NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry);
-
-			String jidToNick(const JID& jid);
-
-			boost::signal<void (const String&)> onOwnNickChanged;
-		private:
-			void handleVCardReceived(const JID& jid, VCard::ref vCard);
-
-		private:
-			JID ownJID_;
-			String ownNick_;
-			XMPPRoster* xmppRoster_;
-			MUCRegistry* mucRegistry_;
-			VCardManager* vcardManager_;
-	};
-}
-
diff --git a/Swift/Controllers/PresenceNotifier.cpp b/Swift/Controllers/PresenceNotifier.cpp
index 466262d..de6b2c9 100644
--- a/Swift/Controllers/PresenceNotifier.cpp
+++ b/Swift/Controllers/PresenceNotifier.cpp
@@ -14,7 +14,7 @@
 #include "Swiften/Roster/XMPPRoster.h"
 #include "Swiften/Presence/PresenceOracle.h"
 #include "Swiften/Network/TimerFactory.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 
 namespace Swift {
 
diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index dfe34b0..2f6c82c 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -11,7 +11,7 @@
 #include "Swiften/Base/foreach.h"
 #include "Swift/Controllers/UIInterfaces/MainWindow.h"
 #include "Swift/Controllers/UIInterfaces/MainWindowFactory.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swiften/Roster/GetRosterRequest.h"
 #include "Swiften/Roster/SetRosterRequest.h"
 #include "Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h"
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index dead16a..d8b2781 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -27,7 +27,6 @@ if env["SCONS_STAGE"] == "build" :
 			"Chat/MUCController.cpp",
 			"Chat/MUCSearchController.cpp",
 			"MainController.cpp",
-			"NickResolver.cpp",
 			"RosterController.cpp",
 			"RosterGroupExpandinessPersister.cpp",
 			"EventWindowController.cpp",
@@ -45,7 +44,6 @@ if env["SCONS_STAGE"] == "build" :
 		])
 
 	env.Append(UNITTEST_SOURCES = [
-			File("UnitTest/NickResolverTest.cpp"),
 			File("UnitTest/RosterControllerTest.cpp"),
 			File("UnitTest/PreviousStatusStoreTest.cpp"),
 			File("UnitTest/PresenceNotifierTest.cpp"),
diff --git a/Swift/Controllers/UnitTest/NickResolverTest.cpp b/Swift/Controllers/UnitTest/NickResolverTest.cpp
deleted file mode 100644
index 2b1e49c..0000000
--- a/Swift/Controllers/UnitTest/NickResolverTest.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#include "Swift/Controllers/NickResolver.h"
-#include "Swiften/MUC/MUCRegistry.h"
-#include "Swiften/Roster/XMPPRosterImpl.h"
-#include "Swiften/VCards/VCardManager.h"
-#include "Swiften/VCards/VCardMemoryStorage.h"
-#include "Swiften/Queries/IQRouter.h"
-#include "Swiften/Client/DummyStanzaChannel.h"
-
-using namespace Swift;
-
-class NickResolverTest : public CppUnit::TestFixture {
-		CPPUNIT_TEST_SUITE(NickResolverTest);
-		CPPUNIT_TEST(testNoMatch);
-		CPPUNIT_TEST(testZeroLengthMatch);
-		CPPUNIT_TEST(testMatch);
-		CPPUNIT_TEST(testOverwrittenMatch);
-		CPPUNIT_TEST(testRemovedMatch);
-		CPPUNIT_TEST(testMUCNick);
-		CPPUNIT_TEST(testMUCNoNick);
-		CPPUNIT_TEST(testRemovedMatch);
-		CPPUNIT_TEST(testOwnNickFullOnly);
-		CPPUNIT_TEST(testOwnNickGivenAndFull);
-		CPPUNIT_TEST(testOwnNickNickEtAl);
-		CPPUNIT_TEST_SUITE_END();
-
-	public:
-		void setUp() {
-			ownJID_ = JID("kev@wonderland.lit");
-			xmppRoster_ = new XMPPRosterImpl();
-			stanzaChannel_ = new DummyStanzaChannel();
-		  iqRouter_ = new IQRouter(stanzaChannel_);
-			vCardStorage_ = new VCardMemoryStorage();
-			vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_);
-			registry_ = new MUCRegistry();
-			resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_);
-		}
-
-		void tearDown() {
-			delete resolver_;
-			delete registry_;
-			delete vCardManager_;
-			delete stanzaChannel_;
-			delete iqRouter_;
-			delete vCardStorage_;
-			delete xmppRoster_;
-		}
-
-		void testMUCNick() {
-			registry_->addMUC(JID("foo@bar"));
-			JID testJID("foo@bar/baz");
-
-			CPPUNIT_ASSERT_EQUAL(String("baz"), resolver_->jidToNick(testJID));
-		}
-
-		void testMUCNoNick() {
-			registry_->addMUC(JID("foo@bar"));
-			JID testJID("foo@bar");
-
-			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
-		}
-
-
-		void testNoMatch() {
-			JID testJID("foo@bar/baz");
-
-			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
-		}
-		
-		void testZeroLengthMatch() {
-			JID testJID("foo@bar/baz");
-			xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both);
-			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
-		}
-
-		void testMatch() {
-			JID testJID("foo@bar/baz");
-			xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both);
-
-			CPPUNIT_ASSERT_EQUAL(String("Test"), resolver_->jidToNick(testJID));
-		}
-
-		void testOverwrittenMatch() {
-			JID testJID("foo@bar/baz");
-			xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both);
-			xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both);
-
-			CPPUNIT_ASSERT_EQUAL(String("Test"), resolver_->jidToNick(testJID));
-		}
-
-		void testRemovedMatch() {
-			JID testJID("foo@bar/baz");
-			xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both);
-			xmppRoster_->removeContact(testJID);
-			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
-		}
-
-		void testOwnNickFullOnly() {
-			populateOwnVCard("", "", "Kevin Smith");
-			CPPUNIT_ASSERT_EQUAL(String("Kevin Smith"), resolver_->jidToNick(ownJID_));
-		}
-
-		void testOwnNickGivenAndFull() {
-			populateOwnVCard("", "Kevin", "Kevin Smith");
-			CPPUNIT_ASSERT_EQUAL(String("Kevin"), resolver_->jidToNick(ownJID_));
-		}
-
-		void testOwnNickNickEtAl() {
-			populateOwnVCard("Kev", "Kevin", "Kevin Smith");
-			CPPUNIT_ASSERT_EQUAL(String("Kev"), resolver_->jidToNick(ownJID_));
-		}
-
-		void populateOwnVCard(const String& nick, const String& given, const String& full) {
-			VCard::ref vcard(new VCard());
-			if (!nick.isEmpty()) {
-				vcard->setNickname(nick);
-			}
-			if (!given.isEmpty()) {
-				vcard->setGivenName(given);
-			}
-			if (!full.isEmpty()) {
-				vcard->setFullName(full);
-			}
-			vCardManager_->requestVCard(ownJID_);
-			IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard));
-			stanzaChannel_->onIQReceived(result);
-		}
-	
-	private:
-		std::vector<String> groups_;
-		XMPPRosterImpl* xmppRoster_;
-		VCardStorage* vCardStorage_;
-		IQRouter* iqRouter_;
-		DummyStanzaChannel* stanzaChannel_;
-		VCardManager* vCardManager_;
-		MUCRegistry* registry_;
-		NickResolver* resolver_;
-		JID ownJID_;
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest);
-
diff --git a/Swift/Controllers/UnitTest/PresenceNotifierTest.cpp b/Swift/Controllers/UnitTest/PresenceNotifierTest.cpp
index 5ebd5df..969555c 100644
--- a/Swift/Controllers/UnitTest/PresenceNotifierTest.cpp
+++ b/Swift/Controllers/UnitTest/PresenceNotifierTest.cpp
@@ -10,7 +10,7 @@
 #include <boost/bind.hpp>
 
 #include "Swift/Controllers/PresenceNotifier.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "SwifTools/Notifier/LoggingNotifier.h"
 #include "Swiften/Client/DummyStanzaChannel.h"
 #include "Swiften/MUC/MUCRegistry.h"
diff --git a/Swift/Controllers/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/UnitTest/RosterControllerTest.cpp
index e4770d7..4dd7b57 100644
--- a/Swift/Controllers/UnitTest/RosterControllerTest.cpp
+++ b/Swift/Controllers/UnitTest/RosterControllerTest.cpp
@@ -25,7 +25,7 @@
 #include "Swift/Controllers/XMPPEvents/EventController.h"
 #include "Swiften/Presence/PresenceOracle.h"
 #include "Swiften/Presence/PresenceSender.h"
-#include "Swift/Controllers/NickResolver.h"
+#include "Swiften/Client/NickResolver.h"
 #include "Swift/Controllers/UIEvents/UIEventStream.h"
 #include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h"
 #include "Swift/Controllers/UIEvents/RegroupRosterItemUIEvent.h"
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 7363c3f..67e2051 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -14,6 +14,11 @@
 #include "Swiften/MUC/MUCRegistry.h"
 #include "Swiften/Client/MemoryStorages.h"
 #include "Swiften/VCards/VCardManager.h"
+#include "Swiften/VCards/VCardManager.h"
+#include "Swiften/Avatars/AvatarManagerImpl.h"
+#include "Swiften/Disco/CapsManager.h"
+#include "Swiften/Disco/EntityCapsManager.h"
+#include "Swiften/Client/NickResolver.h"
 
 namespace Swift {
 
@@ -35,9 +40,19 @@ Client::Client(const JID& jid, const String& password, Storages* storages) : Cor
 	mucRegistry = new MUCRegistry();
 
 	vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage());
+	avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), mucRegistry);
+	capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter());
+	entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel());
+
+	nickResolver = new NickResolver(jid.toBare(), roster, vcardManager, mucRegistry);
 }
 
 Client::~Client() {
+	delete nickResolver;
+
+	delete entityCapsManager;
+	delete capsManager;
+	delete avatarManager;
 	delete vcardManager;
 
 	delete mucRegistry;
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 22fc636..342fe76 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -19,6 +19,10 @@ namespace Swift {
 	class Storages;
 	class MemoryStorages;
 	class VCardManager;
+	class AvatarManager;
+	class CapsManager;
+	class EntityCapsManager;
+	class NickResolver;
 
 	/**
 	 * Provides the core functionality for writing XMPP client software.
@@ -90,6 +94,17 @@ namespace Swift {
 				return vcardManager;
 			}
 
+			AvatarManager* getAvatarManager() const {
+				return avatarManager;
+			}
+			EntityCapsManager* getEntityCapsManager() const {
+				return entityCapsManager;
+			}
+
+			NickResolver* getNickResolver() const {
+				return nickResolver;
+			}
+
 		public:
 			/**
 			 * This signal is emitted when a JID changes presence.
@@ -114,5 +129,9 @@ namespace Swift {
 			PresenceSender* presenceSender;
 			MUCRegistry* mucRegistry;
 			VCardManager* vcardManager;
+			AvatarManager* avatarManager;
+			CapsManager* capsManager;
+			EntityCapsManager* entityCapsManager;
+			NickResolver* nickResolver;
 	};
 }
diff --git a/Swiften/Client/NickResolver.cpp b/Swiften/Client/NickResolver.cpp
new file mode 100644
index 0000000..d06a94d
--- /dev/null
+++ b/Swiften/Client/NickResolver.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Client/NickResolver.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+
+#include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/Roster/XMPPRoster.h"
+#include "Swiften/VCards/VCardManager.h"
+
+// FIXME: The NickResolver currently relies on the vcard being requested by the client on login.
+// The VCardManager should get an onConnected() signal (which is signalled when the stanzachannel is available(, and each time this is emitted,
+// the nickresolver should request the vcard.
+
+namespace Swift {
+
+NickResolver::NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry) : ownJID_(ownJID) {
+	xmppRoster_ = xmppRoster;
+	vcardManager_ = vcardManager;
+	if (vcardManager_) {
+		vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2));
+	}
+	mucRegistry_ = mucRegistry;
+}
+
+String NickResolver::jidToNick(const JID& jid) {
+	if (jid.toBare() == ownJID_) {
+		if (!ownNick_.isEmpty()) {
+			return ownNick_;
+		}
+	}
+	String nick;
+
+	if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) {
+		return jid.getResource().isEmpty() ? jid.toBare().toString() : jid.getResource();
+	}
+
+	if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).isEmpty()) {
+		return xmppRoster_->getNameForJID(jid);
+	}
+
+	return jid.toBare();
+}
+
+void NickResolver::handleVCardReceived(const JID& jid, VCard::ref ownVCard) {
+	if (!jid.equals(ownJID_, JID::WithoutResource)) {
+		return;
+	}
+	String initialNick = ownNick_;
+	ownNick_ = ownJID_.toString();
+	if (ownVCard) {
+		if (!ownVCard->getNickname().isEmpty()) {
+			ownNick_ = ownVCard->getNickname();
+		} else if (!ownVCard->getGivenName().isEmpty()) {
+			ownNick_ = ownVCard->getGivenName();
+		} else if (!ownVCard->getFullName().isEmpty()) {
+			ownNick_ = ownVCard->getFullName();
+		}
+	}
+	if (ownNick_ != initialNick) {
+		onOwnNickChanged(ownNick_);
+	}
+}
+
+}
+
diff --git a/Swiften/Client/NickResolver.h b/Swiften/Client/NickResolver.h
new file mode 100644
index 0000000..7f00acd
--- /dev/null
+++ b/Swiften/Client/NickResolver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <map>
+#include <boost/signals.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Elements/VCard.h"
+
+namespace Swift {
+	class XMPPRoster;
+	class MUCRegistry;
+	class VCardManager;
+	class NickResolver {
+		public:
+			NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry);
+
+			String jidToNick(const JID& jid);
+
+			boost::signal<void (const String&)> onOwnNickChanged;
+		private:
+			void handleVCardReceived(const JID& jid, VCard::ref vCard);
+
+		private:
+			JID ownJID_;
+			String ownNick_;
+			XMPPRoster* xmppRoster_;
+			MUCRegistry* mucRegistry_;
+			VCardManager* vcardManager_;
+	};
+}
+
diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp
new file mode 100644
index 0000000..f4db2c1
--- /dev/null
+++ b/Swiften/Client/UnitTest/NickResolverTest.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Client/NickResolver.h"
+#include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/Roster/XMPPRosterImpl.h"
+#include "Swiften/VCards/VCardManager.h"
+#include "Swiften/VCards/VCardMemoryStorage.h"
+#include "Swiften/Queries/IQRouter.h"
+#include "Swiften/Client/DummyStanzaChannel.h"
+
+using namespace Swift;
+
+class NickResolverTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(NickResolverTest);
+		CPPUNIT_TEST(testNoMatch);
+		CPPUNIT_TEST(testZeroLengthMatch);
+		CPPUNIT_TEST(testMatch);
+		CPPUNIT_TEST(testOverwrittenMatch);
+		CPPUNIT_TEST(testRemovedMatch);
+		CPPUNIT_TEST(testMUCNick);
+		CPPUNIT_TEST(testMUCNoNick);
+		CPPUNIT_TEST(testRemovedMatch);
+		CPPUNIT_TEST(testOwnNickFullOnly);
+		CPPUNIT_TEST(testOwnNickGivenAndFull);
+		CPPUNIT_TEST(testOwnNickNickEtAl);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void setUp() {
+			ownJID_ = JID("kev@wonderland.lit");
+			xmppRoster_ = new XMPPRosterImpl();
+			stanzaChannel_ = new DummyStanzaChannel();
+		  iqRouter_ = new IQRouter(stanzaChannel_);
+			vCardStorage_ = new VCardMemoryStorage();
+			vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_);
+			registry_ = new MUCRegistry();
+			resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_);
+		}
+
+		void tearDown() {
+			delete resolver_;
+			delete registry_;
+			delete vCardManager_;
+			delete stanzaChannel_;
+			delete iqRouter_;
+			delete vCardStorage_;
+			delete xmppRoster_;
+		}
+
+		void testMUCNick() {
+			registry_->addMUC(JID("foo@bar"));
+			JID testJID("foo@bar/baz");
+
+			CPPUNIT_ASSERT_EQUAL(String("baz"), resolver_->jidToNick(testJID));
+		}
+
+		void testMUCNoNick() {
+			registry_->addMUC(JID("foo@bar"));
+			JID testJID("foo@bar");
+
+			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
+		}
+
+
+		void testNoMatch() {
+			JID testJID("foo@bar/baz");
+
+			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
+		}
+		
+		void testZeroLengthMatch() {
+			JID testJID("foo@bar/baz");
+			xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both);
+			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
+		}
+
+		void testMatch() {
+			JID testJID("foo@bar/baz");
+			xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both);
+
+			CPPUNIT_ASSERT_EQUAL(String("Test"), resolver_->jidToNick(testJID));
+		}
+
+		void testOverwrittenMatch() {
+			JID testJID("foo@bar/baz");
+			xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both);
+			xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both);
+
+			CPPUNIT_ASSERT_EQUAL(String("Test"), resolver_->jidToNick(testJID));
+		}
+
+		void testRemovedMatch() {
+			JID testJID("foo@bar/baz");
+			xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both);
+			xmppRoster_->removeContact(testJID);
+			CPPUNIT_ASSERT_EQUAL(String("foo@bar"), resolver_->jidToNick(testJID));
+		}
+
+		void testOwnNickFullOnly() {
+			populateOwnVCard("", "", "Kevin Smith");
+			CPPUNIT_ASSERT_EQUAL(String("Kevin Smith"), resolver_->jidToNick(ownJID_));
+		}
+
+		void testOwnNickGivenAndFull() {
+			populateOwnVCard("", "Kevin", "Kevin Smith");
+			CPPUNIT_ASSERT_EQUAL(String("Kevin"), resolver_->jidToNick(ownJID_));
+		}
+
+		void testOwnNickNickEtAl() {
+			populateOwnVCard("Kev", "Kevin", "Kevin Smith");
+			CPPUNIT_ASSERT_EQUAL(String("Kev"), resolver_->jidToNick(ownJID_));
+		}
+
+		void populateOwnVCard(const String& nick, const String& given, const String& full) {
+			VCard::ref vcard(new VCard());
+			if (!nick.isEmpty()) {
+				vcard->setNickname(nick);
+			}
+			if (!given.isEmpty()) {
+				vcard->setGivenName(given);
+			}
+			if (!full.isEmpty()) {
+				vcard->setFullName(full);
+			}
+			vCardManager_->requestVCard(ownJID_);
+			IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard));
+			stanzaChannel_->onIQReceived(result);
+		}
+	
+	private:
+		std::vector<String> groups_;
+		XMPPRosterImpl* xmppRoster_;
+		VCardStorage* vCardStorage_;
+		IQRouter* iqRouter_;
+		DummyStanzaChannel* stanzaChannel_;
+		VCardManager* vCardManager_;
+		MUCRegistry* registry_;
+		NickResolver* resolver_;
+		JID ownJID_;
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest);
+
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 543029d..90f8d98 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -35,6 +35,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Client/ClientSession.cpp",
 			"Client/MemoryStorages.cpp",
 			"Client/FileStorages.cpp",
+			"Client/NickResolver.cpp",
 			"Compress/ZLibCodecompressor.cpp",
 			"Compress/ZLibDecompressor.cpp",
 			"Compress/ZLibCompressor.cpp",
@@ -161,6 +162,7 @@ if env["SCONS_STAGE"] == "build" :
 			File("Chat/UnitTest/ChatStateNotifierTest.cpp"),
 #		File("Chat/UnitTest/ChatStateTrackerTest.cpp"),
 			File("Client/UnitTest/ClientSessionTest.cpp"),
+			File("Client/UnitTest/NickResolverTest.cpp"),
 			File("Compress/UnitTest/ZLibCompressorTest.cpp"),
 			File("Compress/UnitTest/ZLibDecompressorTest.cpp"),
 			File("Component/UnitTest/ComponentHandshakeGeneratorTest.cpp"),
-- 
cgit v0.10.2-6-g49f6