From b8201141afdbd4cab6fcda37cf8daad492b1f996 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 14 Sep 2009 20:57:59 +0200
Subject: Added private storage element, parser, and serializer.


diff --git a/Swiften/Elements/PrivateStorage.h b/Swiften/Elements/PrivateStorage.h
new file mode 100644
index 0000000..66259a3
--- /dev/null
+++ b/Swiften/Elements/PrivateStorage.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Elements/Payload.h"
+
+namespace Swift {
+	class PrivateStorage : public Payload {
+		public:
+			PrivateStorage() {
+			}
+
+			boost::shared_ptr<Payload> getPayload() const {
+				return payload;
+			}
+
+			void setPayload(boost::shared_ptr<Payload> p) {
+				payload = p;
+			}
+
+		private:
+			boost::shared_ptr<Payload> payload;
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index f4a7b9d..eb4cda0 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -18,6 +18,7 @@
 #include "Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/VCardParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h"
 
 using namespace boost;
 
@@ -39,6 +40,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelsCatalogParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardParserFactory()));
+	factories_.push_back(shared_ptr<PayloadParserFactory>(new PrivateStorageParserFactory(this)));
 	foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
 		addFactory(factory.get());
 	}
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp
new file mode 100644
index 0000000..5c3af26
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp
@@ -0,0 +1,43 @@
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+#include "Swiften/Parser/PayloadParserFactoryCollection.h"
+#include "Swiften/Parser/PayloadParserFactory.h"
+
+namespace Swift {
+
+PrivateStorageParser::PrivateStorageParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) {
+}
+
+void PrivateStorageParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+	if (level == 1) {
+		PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes);
+		if (payloadParserFactory) {
+			currentPayloadParser.reset(payloadParserFactory->createPayloadParser());
+		}
+	}
+
+	if (level >= 1 && currentPayloadParser.get()) {
+		currentPayloadParser->handleStartElement(element, ns, attributes);
+	}
+	++level;
+}
+
+void PrivateStorageParser::handleEndElement(const String& element, const String& ns) {
+	--level;
+	if (currentPayloadParser.get()) {
+		if (level >= 1) {
+			currentPayloadParser->handleEndElement(element, ns);
+		}
+
+		if (level == 1) {
+			getPayloadInternal()->setPayload(currentPayloadParser->getPayload());
+		}
+	}
+}
+
+void PrivateStorageParser::handleCharacterData(const String& data) {
+	if (level > 1 && currentPayloadParser.get()) {
+		currentPayloadParser->handleCharacterData(data);
+	}
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.h b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h
new file mode 100644
index 0000000..fae0f10
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "Swiften/Elements/PrivateStorage.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+	class PayloadParserFactoryCollection;
+
+	class PrivateStorageParser : public GenericPayloadParser<PrivateStorage> {
+		public:
+			PrivateStorageParser(PayloadParserFactoryCollection* factories);
+
+		private:
+			virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+			virtual void handleEndElement(const String& element, const String&);
+			virtual void handleCharacterData(const String& data);
+
+		private:
+			PayloadParserFactoryCollection* factories;
+			int level;
+			std::auto_ptr<PayloadParser> currentPayloadParser;
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h
new file mode 100644
index 0000000..4d9c02b
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+
+namespace Swift {
+	class PayloadParserFactoryCollection;
+
+	class PrivateStorageParserFactory : public PayloadParserFactory {
+		public:
+			PrivateStorageParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) {
+			}
+
+			virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const {
+				return element == "query" && ns == "jabber:iq:private";
+			}
+
+			virtual PayloadParser* createPayloadParser() {
+				return new PrivateStorageParser(factories);
+			}
+
+		private:
+			PayloadParserFactoryCollection* factories;
+			
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp
new file mode 100644
index 0000000..e820083
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp
@@ -0,0 +1,89 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Elements/Storage.h"
+#include "Swiften/Parser/PayloadParsers/PrivateStorageParser.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h"
+
+using namespace Swift;
+
+class PrivateStorageParserTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(PrivateStorageParserTest);
+		CPPUNIT_TEST(testParse);
+		CPPUNIT_TEST(testParse_NoPayload);
+		CPPUNIT_TEST(testParse_MultiplePayloads);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		PrivateStorageParserTest() {}
+
+		void testParse() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<query xmlns='jabber:iq:private'>"
+					"<storage xmlns='storage:bookmarks'>"
+						"<conference name='Swift' jid='swift@rooms.swift.im'>"
+							"<nick>Alice</nick>"
+						"</conference>"
+					"</storage>"
+				"</query>"));
+
+			boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+			CPPUNIT_ASSERT(payload);
+			boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
+			CPPUNIT_ASSERT(storage);
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), storage->getConferences()[0].nick);
+			CPPUNIT_ASSERT_EQUAL(JID("swift@rooms.swift.im"), storage->getConferences()[0].jid);
+		}
+
+		void testParse_NoPayload() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:private'/>"));
+
+			boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+			CPPUNIT_ASSERT(payload);
+			CPPUNIT_ASSERT(!payload->getPayload());
+		}
+
+		void testParse_MultiplePayloads() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<query xmlns='jabber:iq:private'>"
+					"<storage xmlns='storage:bookmarks'>"
+						"<conference name='Swift' jid='swift@rooms.swift.im'>"
+							"<nick>Alice</nick>"
+						"</conference>"
+					"</storage>"
+					"<storage xmlns='storage:bookmarks'>"
+						"<conference name='Swift' jid='swift@rooms.swift.im'>"
+							"<nick>Rabbit</nick>"
+						"</conference>"
+					"</storage>"
+				"</query>"));
+
+			boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload());
+			CPPUNIT_ASSERT(payload);
+			boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
+			CPPUNIT_ASSERT(storage);
+			CPPUNIT_ASSERT_EQUAL(String("Rabbit"), storage->getConferences()[0].nick);
+		}
+
+		void testParse_UnsupportedPayload() {
+			PayloadParserFactoryCollection factories;
+			PrivateStorageParser testling(&factories);
+			PayloadParserTester parser(&testling);
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<query xmlns='jabber:iq:private'>"
+					"<foo>Bar</foo>"
+				"</query>"));
+
+			CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<PrivateStorage>(testling.getPayload())->getPayload());
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PrivateStorageParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
index 0cd0100..3fbf27a 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp
@@ -6,8 +6,7 @@
 
 using namespace Swift;
 
-class StorageParserTest : public CppUnit::TestFixture
-{
+class StorageParserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(StorageParserTest);
 		CPPUNIT_TEST(testParse_Conference);
 		CPPUNIT_TEST(testParse_MultipleConferences);
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index e3cd288..3330775 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -19,6 +19,7 @@ sources = [
 		"PayloadParsers/ErrorParser.cpp",
 		"PayloadParsers/FullPayloadParserFactoryCollection.cpp",
 		"PayloadParsers/PriorityParser.cpp",
+		"PayloadParsers/PrivateStorageParser.cpp",
 		"PayloadParsers/RawXMLPayloadParser.cpp",
 		"PayloadParsers/ResourceBindParser.cpp",
 		"PayloadParsers/RosterParser.cpp",
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 6572e9a..fa10fb1 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -62,6 +62,7 @@ sources = [
 		"Serializer/PayloadSerializers/VCardSerializer.cpp",
 		"Serializer/PayloadSerializers/VCardUpdateSerializer.cpp",
 		"Serializer/PayloadSerializers/StorageSerializer.cpp",
+		"Serializer/PayloadSerializers/PrivateStorageSerializer.cpp",
 		"Serializer/PresenceSerializer.cpp",
 		"Serializer/StanzaSerializer.cpp",
 		"Serializer/StreamFeaturesSerializer.cpp",
@@ -130,6 +131,7 @@ env.Append(UNITTEST_SOURCES = [
 		File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"),
 		File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"),
 		File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"),
+		File("Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp"),
 		File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"),
 		File("Parser/UnitTest/AttributeMapTest.cpp"),
 		File("Parser/UnitTest/IQParserTest.cpp"),
@@ -162,6 +164,7 @@ env.Append(UNITTEST_SOURCES = [
 		File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp"),
 		File("Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp"),
 		File("Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp"),
+		File("Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp"),
 		File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"),
 		File("Serializer/XML/UnitTest/XMLElementTest.cpp"),
 		File("Server/UnitTest/ServerStanzaRouterTest.cpp"),
diff --git a/Swiften/Serializer/PayloadSerializerCollection.h b/Swiften/Serializer/PayloadSerializerCollection.h
index a126989..63ccabe 100644
--- a/Swiften/Serializer/PayloadSerializerCollection.h
+++ b/Swiften/Serializer/PayloadSerializerCollection.h
@@ -1,5 +1,4 @@
-#ifndef SWIFTEN_PAYLOADSERIALIZERCOLLECTION_H
-#define SWIFTEN_PAYLOADSERIALIZERCOLLECTION_H
+#pragma once
 
 #include <vector>
 #include <boost/shared_ptr.hpp>
@@ -22,5 +21,3 @@ namespace Swift {
 			std::vector<PayloadSerializer*> serializers_;
 	};
 }
-
-#endif
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 998dce8..fc20018 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -19,6 +19,7 @@
 #include "Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h"
 #include "Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h"
 #include "Swiften/Serializer/PayloadSerializers/StorageSerializer.h"
+#include "Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h"
 
 namespace Swift {
 
@@ -41,6 +42,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
 	serializers_.push_back(new VCardUpdateSerializer());
 	serializers_.push_back(new RawXMLPayloadSerializer());
 	serializers_.push_back(new StorageSerializer());
+	serializers_.push_back(new PrivateStorageSerializer(this));
 	foreach(PayloadSerializer* serializer, serializers_) {
 		addSerializer(serializer);
 	}
diff --git a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp
new file mode 100644
index 0000000..999252c
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp
@@ -0,0 +1,28 @@
+#include "Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Serializer/XML/XMLElement.h"
+#include "Swiften/Serializer/XML/XMLTextNode.h"
+#include "Swiften/Serializer/XML/XMLRawTextNode.h"
+#include "Swiften/Serializer/PayloadSerializerCollection.h"
+
+namespace Swift {
+
+PrivateStorageSerializer::PrivateStorageSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) {
+}
+
+String PrivateStorageSerializer::serializePayload(boost::shared_ptr<PrivateStorage> storage)	const {
+	XMLElement storageElement("query", "jabber:iq:private");
+	boost::shared_ptr<Payload> payload = storage->getPayload();
+	if (payload) {
+		PayloadSerializer* serializer = serializers->getPayloadSerializer(payload);
+		if (serializer) {
+			storageElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(payload))));
+		}
+	}
+	return storageElement.serialize();
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h
new file mode 100644
index 0000000..c655634
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Swiften/Serializer/GenericPayloadSerializer.h"
+#include "Swiften/Elements/PrivateStorage.h"
+
+namespace Swift {
+	class PayloadSerializerCollection;
+
+	class PrivateStorageSerializer : public GenericPayloadSerializer<PrivateStorage> {
+		public:
+			PrivateStorageSerializer(PayloadSerializerCollection* serializers);
+
+			virtual String serializePayload(boost::shared_ptr<PrivateStorage>)  const;
+
+		private:
+			PayloadSerializerCollection* serializers;
+	};
+}
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp
new file mode 100644
index 0000000..37c3adb
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp
@@ -0,0 +1,44 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h"
+#include "Swiften/Elements/PrivateStorage.h"
+#include "Swiften/Elements/Storage.h"
+
+using namespace Swift;
+
+class PrivateStorageSerializerTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(PrivateStorageSerializerTest);
+		CPPUNIT_TEST(testSerialize);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		PrivateStorageSerializerTest() {}
+
+		void testSerialize() {
+			PayloadsSerializer serializer;
+
+			boost::shared_ptr<PrivateStorage> privateStorage(new PrivateStorage());
+			boost::shared_ptr<Storage> storage(new Storage());
+			Storage::Conference conference;
+			conference.name = "Swift";
+			conference.jid = JID("swift@rooms.swift.im");
+			conference.nick = "Alice";
+			storage->addConference(conference);
+			privateStorage->setPayload(storage);
+
+			CPPUNIT_ASSERT_EQUAL(String(
+				"<query xmlns=\"jabber:iq:private\">"	
+					"<storage xmlns=\"storage:bookmarks\">"
+						"<conference "
+								"autojoin=\"1\" "
+								"jid=\"swift@rooms.swift.im\" "
+								"name=\"Swift\">"
+							"<nick>Alice</nick>"
+						"</conference>"
+					"</storage>"
+				"</query>"), serializer.serialize(privateStorage));
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PrivateStorageSerializerTest);
-- 
cgit v0.10.2-6-g49f6