From e1a2d258479cd915e8c30c5c996b58da3da3e55d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 11 Jul 2009 17:27:08 +0200
Subject: PayloadParserFactoryCollection additions.

Added the ability to set a default PayloadParserFactory.
Check factories in reverse order.
Add PayloadParserFactoryCollection unit test.

diff --git a/Swiften/Parser/PayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParserFactoryCollection.cpp
index f361ce8..6d3a4cf 100644
--- a/Swiften/Parser/PayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParserFactoryCollection.cpp
@@ -6,7 +6,7 @@
 
 namespace Swift {
 
-PayloadParserFactoryCollection::PayloadParserFactoryCollection() {
+PayloadParserFactoryCollection::PayloadParserFactoryCollection() : defaultFactory_(NULL) {
 }
 
 void PayloadParserFactoryCollection::addFactory(PayloadParserFactory* factory) {
@@ -17,11 +17,15 @@ void PayloadParserFactoryCollection::removeFactory(PayloadParserFactory* factory
 	factories_.erase(remove(factories_.begin(), factories_.end(), factory), factories_.end());
 }
 
+void PayloadParserFactoryCollection::setDefaultFactory(PayloadParserFactory* factory) {
+	defaultFactory_ = factory;
+}
+
 PayloadParserFactory* PayloadParserFactoryCollection::getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes) {
-	std::vector<PayloadParserFactory*>::const_iterator i = std::find_if(
-			factories_.begin(), factories_.end(), 
+	std::vector<PayloadParserFactory*>::reverse_iterator i = std::find_if(
+			factories_.rbegin(), factories_.rend(), 
 			boost::bind(&PayloadParserFactory::canParse, _1, element, ns, attributes));
-	return (i != factories_.end() ? *i : NULL);
+	return (i != factories_.rend() ? *i : defaultFactory_);
 }
 
 }
diff --git a/Swiften/Parser/PayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParserFactoryCollection.h
index fad94c3..80a763b 100644
--- a/Swiften/Parser/PayloadParserFactoryCollection.h
+++ b/Swiften/Parser/PayloadParserFactoryCollection.h
@@ -15,10 +15,13 @@ namespace Swift {
 
 			void addFactory(PayloadParserFactory* factory);
 			void removeFactory(PayloadParserFactory* factory);
+			void setDefaultFactory(PayloadParserFactory* factory);
+
 			PayloadParserFactory* getPayloadParserFactory(const String& element, const String& ns, const AttributeMap& attributes);
 
 		private:
 			std::vector<PayloadParserFactory*> factories_;
+			PayloadParserFactory* defaultFactory_;
 	};
 }
 
diff --git a/Swiften/Parser/UnitTest/Makefile.inc b/Swiften/Parser/UnitTest/Makefile.inc
index 4f9c59e..be570d2 100644
--- a/Swiften/Parser/UnitTest/Makefile.inc
+++ b/Swiften/Parser/UnitTest/Makefile.inc
@@ -1,4 +1,5 @@
 UNITTEST_SOURCES += \
+	Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp \
 	Swiften/Parser/UnitTest/XMPPParserTest.cpp \
 	Swiften/Parser/UnitTest/StanzaParserTest.cpp \
 	Swiften/Parser/UnitTest/MessageParserTest.cpp \
diff --git a/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp
new file mode 100644
index 0000000..bfd2c2c
--- /dev/null
+++ b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp
@@ -0,0 +1,97 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+using namespace Swift;
+
+class PayloadParserFactoryCollectionTest : public CppUnit::TestFixture
+{
+		CPPUNIT_TEST_SUITE(PayloadParserFactoryCollectionTest);
+		CPPUNIT_TEST(testGetPayloadParserFactory);
+		CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchingFactory);
+		CPPUNIT_TEST(testGetPayloadParserFactory_TwoMatchingFactories);
+		CPPUNIT_TEST(testGetPayloadParserFactory_MatchWithDefaultFactory);
+		CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchWithDefaultFactory);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		PayloadParserFactoryCollectionTest() {}
+
+		void setUp() {
+		}
+
+		void tearDown() {
+		}
+
+		void testGetPayloadParserFactory() {
+			PayloadParserFactoryCollection testling;
+			DummyFactory factory1("foo");
+			testling.addFactory(&factory1);
+			DummyFactory factory2("bar");
+			testling.addFactory(&factory2);
+			DummyFactory factory3("baz");
+			testling.addFactory(&factory3);
+
+			PayloadParserFactory* factory = testling.getPayloadParserFactory("bar", "", AttributeMap());
+
+			CPPUNIT_ASSERT(factory == &factory2);
+		}
+
+		void testGetPayloadParserFactory_NoMatchingFactory() {
+			PayloadParserFactoryCollection testling;
+			DummyFactory factory("foo");
+
+			CPPUNIT_ASSERT(!testling.getPayloadParserFactory("bar", "", AttributeMap()));
+		}
+
+		void testGetPayloadParserFactory_TwoMatchingFactories() {
+			PayloadParserFactoryCollection testling;
+			DummyFactory factory1("foo");
+			testling.addFactory(&factory1);
+			DummyFactory factory2("foo");
+			testling.addFactory(&factory2);
+
+			PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap());
+
+			CPPUNIT_ASSERT(factory == &factory2);
+		}
+
+		void testGetPayloadParserFactory_MatchWithDefaultFactory() {
+			PayloadParserFactoryCollection testling;
+			DummyFactory factory1("foo");
+			testling.addFactory(&factory1);
+			DummyFactory factory2;
+			testling.setDefaultFactory(&factory2);
+
+			PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap());
+
+			CPPUNIT_ASSERT(factory == &factory1);
+		}
+
+		void testGetPayloadParserFactory_NoMatchWithDefaultFactory() {
+			PayloadParserFactoryCollection testling;
+			DummyFactory factory1("foo");
+			testling.addFactory(&factory1);
+			DummyFactory factory2;
+			testling.setDefaultFactory(&factory2);
+
+			PayloadParserFactory* factory = testling.getPayloadParserFactory("baz", "", AttributeMap());
+
+			CPPUNIT_ASSERT(factory == &factory2);
+		}
+	
+	
+	private:
+		struct DummyFactory : public PayloadParserFactory {
+			DummyFactory(const String& element = "") : element(element) {}
+			virtual bool canParse(const String& e, const String&, const AttributeMap&) const {
+				return element.isEmpty() ? true : element == e;
+			}
+			virtual PayloadParser* createPayloadParser() { return NULL; }
+			String element;
+		};
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PayloadParserFactoryCollectionTest);
-- 
cgit v0.10.2-6-g49f6