diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-08-22 08:55:08 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-08-24 17:10:23 (GMT) |
commit | b6a34463dfcedd454ab42230a47cdb7294a76f21 (patch) | |
tree | 832b0243325451932c0d15e9e33d53948fce0110 /Swiften/VCards | |
parent | 6e4b357141a6d09632f1e96d0eaf54f79daf52c9 (diff) | |
download | swift-b6a34463dfcedd454ab42230a47cdb7294a76f21.zip swift-b6a34463dfcedd454ab42230a47cdb7294a76f21.tar.bz2 |
Implemented VCardManager.
Diffstat (limited to 'Swiften/VCards')
-rw-r--r-- | Swiften/VCards/SConscript | 1 | ||||
-rw-r--r-- | Swiften/VCards/UnitTest/VCardManagerTest.cpp | 159 | ||||
-rw-r--r-- | Swiften/VCards/VCardFileStorage.cpp | 4 | ||||
-rw-r--r-- | Swiften/VCards/VCardFileStorage.h | 4 | ||||
-rw-r--r-- | Swiften/VCards/VCardFileStorageFactory.h | 2 | ||||
-rw-r--r-- | Swiften/VCards/VCardManager.cpp | 42 | ||||
-rw-r--r-- | Swiften/VCards/VCardManager.h | 23 | ||||
-rw-r--r-- | Swiften/VCards/VCardMemoryStorage.h | 38 | ||||
-rw-r--r-- | Swiften/VCards/VCardStorage.h | 4 |
9 files changed, 263 insertions, 14 deletions
diff --git a/Swiften/VCards/SConscript b/Swiften/VCards/SConscript index 538eb4a..e83e633 100644 --- a/Swiften/VCards/SConscript +++ b/Swiften/VCards/SConscript @@ -1,6 +1,7 @@ Import("swiften_env") objects = swiften_env.StaticObject([ + "VCardManager.cpp", "VCardStorage.cpp", "VCardFileStorage.cpp", "VCardStorageFactory.cpp", diff --git a/Swiften/VCards/UnitTest/VCardManagerTest.cpp b/Swiften/VCards/UnitTest/VCardManagerTest.cpp new file mode 100644 index 0000000..927bcfe --- /dev/null +++ b/Swiften/VCards/UnitTest/VCardManagerTest.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * 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 <vector> +#include <boost/bind.hpp> + +#include "Swiften/VCards/VCardManager.h" +#include "Swiften/VCards/VCardMemoryStorage.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Client/DummyStanzaChannel.h" + +using namespace Swift; + +class VCardManagerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(VCardManagerTest); + CPPUNIT_TEST(testGet_NewVCardRequestsVCard); + CPPUNIT_TEST(testGet_ExistingVCard); + CPPUNIT_TEST(testRequest_RequestsVCard); + CPPUNIT_TEST(testRequest_ReceiveEmitsNotification); + CPPUNIT_TEST(testRequest_Error); + CPPUNIT_TEST(testRequest_VCardAlreadyRequested); + CPPUNIT_TEST(testRequest_AfterPreviousRequest); + CPPUNIT_TEST(testRequestOwnVCard); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + ownJID = JID("baz@fum.com/dum"); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + vcardStorage = new VCardMemoryStorage(); + } + + void tearDown() { + delete vcardStorage; + delete iqRouter; + delete stanzaChannel; + } + + void testGet_NewVCardRequestsVCard() { + std::auto_ptr<VCardManager> testling = createManager(); + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT(!result); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testGet_ExistingVCard() { + std::auto_ptr<VCardManager> testling = createManager(); + VCard::ref vcard(new VCard()); + vcard->setFullName("Foo Bar"); + vcardStorage->setVCard(JID("foo@bar.com/baz"), vcard); + + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(String("Foo Bar"), result->getFullName()); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testRequest_RequestsVCard() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testRequest_ReceiveEmitsNotification() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(createVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); + CPPUNIT_ASSERT_EQUAL(String("Foo Bar"), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(String("Foo Bar"), vcardStorage->getVCard(JID("foo@bar.com/baz"))->getFullName()); + } + + void testRequest_Error() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); + CPPUNIT_ASSERT_EQUAL(String(""), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(String(""), vcardStorage->getVCard(JID("foo@bar.com/baz"))->getFullName()); + } + + void testRequest_VCardAlreadyRequested() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT(!result); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testRequest_AfterPreviousRequest() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(createVCardResult()); + testling->requestVCard(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(1, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testRequestOwnVCard() { + std::auto_ptr<VCardManager> testling = createManager(); + testling->requestVCard(ownJID); + stanzaChannel->onIQReceived(createOwnVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(ownJID.toBare(), changes[0].first); + CPPUNIT_ASSERT_EQUAL(String("Myself"), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(String("Myself"), vcardStorage->getVCard(ownJID.toBare())->getFullName()); + } + + private: + std::auto_ptr<VCardManager> createManager() { + std::auto_ptr<VCardManager> manager(new VCardManager(ownJID, iqRouter, vcardStorage)); + manager->onVCardChanged.connect(boost::bind(&VCardManagerTest::handleVCardChanged, this, _1, _2)); + return manager; + } + + void handleVCardChanged(const JID& jid, VCard::ref vcard) { + changes.push_back(std::pair<JID, VCard::ref>(jid, vcard)); + } + + IQ::ref createVCardResult() { + VCard::ref vcard(new VCard()); + vcard->setFullName("Foo Bar"); + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getID(), vcard); + } + + IQ::ref createOwnVCardResult() { + VCard::ref vcard(new VCard()); + vcard->setFullName("Myself"); + return IQ::createResult(JID(), stanzaChannel->sentStanzas[0]->getID(), vcard); + } + + private: + JID ownJID; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + VCardMemoryStorage* vcardStorage; + std::vector< std::pair<JID, VCard::ref> > changes; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(VCardManagerTest); diff --git a/Swiften/VCards/VCardFileStorage.cpp b/Swiften/VCards/VCardFileStorage.cpp index d3163fb..66bae04 100644 --- a/Swiften/VCards/VCardFileStorage.cpp +++ b/Swiften/VCards/VCardFileStorage.cpp @@ -47,7 +47,9 @@ void VCardFileStorage::setVCard(const JID& jid, boost::shared_ptr<VCard> v) { } boost::filesystem::path VCardFileStorage::getVCardPath(const JID& jid) const { - return boost::filesystem::path(vcardsPath / (jid.toBare().toString().getUTF8String() + ".xml")); + String file(jid.toString()); + file.replaceAll('/', "%2f"); + return boost::filesystem::path(vcardsPath / (file.getUTF8String() + ".xml")); } } diff --git a/Swiften/VCards/VCardFileStorage.h b/Swiften/VCards/VCardFileStorage.h index d75ac92..5f8cb1a 100644 --- a/Swiften/VCards/VCardFileStorage.h +++ b/Swiften/VCards/VCardFileStorage.h @@ -16,8 +16,8 @@ namespace Swift { public: VCardFileStorage(boost::filesystem::path dir); - virtual boost::shared_ptr<VCard> getVCard(const JID& jid) const; - virtual void setVCard(const JID& jid, boost::shared_ptr<VCard> v); + virtual VCard::ref getVCard(const JID& jid) const; + virtual void setVCard(const JID& jid, VCard::ref v); private: boost::filesystem::path getVCardPath(const JID&) const; diff --git a/Swiften/VCards/VCardFileStorageFactory.h b/Swiften/VCards/VCardFileStorageFactory.h index 136c6a7..27e50af 100644 --- a/Swiften/VCards/VCardFileStorageFactory.h +++ b/Swiften/VCards/VCardFileStorageFactory.h @@ -18,7 +18,7 @@ namespace Swift { } virtual VCardStorage* createVCardStorage(const String& profile) { - return new VCardFileStorage(base / profile.getUTF8String()); + return new VCardFileStorage(base / profile.getUTF8String() / "vcards"); } private: diff --git a/Swiften/VCards/VCardManager.cpp b/Swiften/VCards/VCardManager.cpp index 0174dea..628f4c8 100644 --- a/Swiften/VCards/VCardManager.cpp +++ b/Swiften/VCards/VCardManager.cpp @@ -6,17 +6,49 @@ #include "Swiften/VCards/VCardManager.h" +#include <boost/bind.hpp> + +#include "Swiften/JID/JID.h" +#include "Swiften/VCards/VCardStorage.h" +#include "Swiften/Queries/Requests/GetVCardRequest.h" + namespace Swift { -VCardManager::VCardManager(IQRouter* iqRouter, VCardStorage* vcardStorage) : iqRouter(iqRouter), storage(vcardStorage) { +VCardManager::VCardManager(const JID& ownJID, IQRouter* iqRouter, VCardStorage* vcardStorage) : ownJID(ownJID), iqRouter(iqRouter), storage(vcardStorage) { } -boost::shared_ptr<VCard> VCardManager::getVCardAndRequestWhenNeeded(const JID& jid) const { - boost::shared_ptr<VCard> vcard = storage->getVCard(jid); +VCard::ref VCardManager::getVCardAndRequestWhenNeeded(const JID& jid) { + VCard::ref vcard = storage->getVCard(jid); if (!vcard) { - // TODO: Request vcard if necessary + requestVCard(jid); } return vcard; } - + +void VCardManager::requestVCard(const JID& requestedJID) { + JID jid = requestedJID.equals(ownJID, JID::WithoutResource) ? JID() : requestedJID; + if (requestedVCards.find(jid) != requestedVCards.end()) { + return; + } + GetVCardRequest::ref request(new GetVCardRequest(jid, iqRouter)); + request->onResponse.connect(boost::bind(&VCardManager::handleVCardReceived, this, jid, _1, _2)); + request->send(); + requestedVCards.insert(jid); +} + +void VCardManager::requestOwnVCard() { + requestVCard(JID()); +} + + +void VCardManager::handleVCardReceived(const JID& actualJID, VCard::ref vcard, const boost::optional<ErrorPayload>& error) { + if (error) { + vcard = VCard::ref(new VCard()); + } + requestedVCards.erase(actualJID); + JID jid = actualJID.isValid() ? actualJID : ownJID.toBare(); + storage->setVCard(jid, vcard); + onVCardChanged(jid, vcard); +} + } diff --git a/Swiften/VCards/VCardManager.h b/Swiften/VCards/VCardManager.h index bbf07c0..fc99128 100644 --- a/Swiften/VCards/VCardManager.h +++ b/Swiften/VCards/VCardManager.h @@ -6,23 +6,40 @@ #pragma once +#include <boost/signals.hpp> +#include <set> + +#include "Swiften/JID/JID.h" #include "Swiften/Elements/VCard.h" +#include "Swiften/Elements/ErrorPayload.h" namespace Swift { class JID; class VCardStorage; + class IQRouter; class VCardManager { public: - VCardManager(IQRouter* iqRouter, VCardStorage* vcardStorage); + VCardManager(const JID& ownJID, IQRouter* iqRouter, VCardStorage* vcardStorage); - virtual boost::shared_ptr<VCard> getVCardAndRequestWhenNeeded(const JID& jid) const ; + VCard::ref getVCardAndRequestWhenNeeded(const JID& jid); + void requestVCard(const JID& jid); + void requestOwnVCard(); public: - boost::signal<void (const JID&)> onVCardChanged; + /** + * The JID will always be bare. + */ + boost::signal<void (const JID&, VCard::ref)> onVCardChanged; + boost::signal<void (VCard::ref)> onOwnVCardChanged; + + private: + void handleVCardReceived(const JID& from, VCard::ref, const boost::optional<ErrorPayload>&); private: + JID ownJID; IQRouter* iqRouter; VCardStorage* storage; + std::set<JID> requestedVCards; }; } diff --git a/Swiften/VCards/VCardMemoryStorage.h b/Swiften/VCards/VCardMemoryStorage.h new file mode 100644 index 0000000..b2e99c6 --- /dev/null +++ b/Swiften/VCards/VCardMemoryStorage.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <map> + +#include "Swiften/JID/JID.h" +#include "Swiften/VCards/VCardStorage.h" + +namespace Swift { + class VCardMemoryStorage : public VCardStorage { + public: + VCardMemoryStorage() {} + + virtual VCard::ref getVCard(const JID& jid) const { + VCardMap::const_iterator i = vcards.find(jid); + if (i != vcards.end()) { + return i->second; + } + else { + return VCard::ref(); + } + } + + virtual void setVCard(const JID& jid, VCard::ref v) { + vcards[jid] = v; + } + + private: + typedef std::map<JID, VCard::ref> VCardMap; + VCardMap vcards; + }; +} diff --git a/Swiften/VCards/VCardStorage.h b/Swiften/VCards/VCardStorage.h index 2a9044c..854ccc6 100644 --- a/Swiften/VCards/VCardStorage.h +++ b/Swiften/VCards/VCardStorage.h @@ -17,7 +17,7 @@ namespace Swift { public: virtual ~VCardStorage(); - virtual boost::shared_ptr<VCard> getVCard(const JID& jid) const = 0; - virtual void setVCard(const JID&, boost::shared_ptr<VCard>) = 0; + virtual VCard::ref getVCard(const JID& jid) const = 0; + virtual void setVCard(const JID&, VCard::ref) = 0; }; } |