From e1f9cdc38b600d930760ed0e0b867ab739127f5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 18 Aug 2010 22:08:34 +0200
Subject: Added command parser.


diff --git a/Swiften/Base/Shared.h b/Swiften/Base/Shared.h
new file mode 100644
index 0000000..612fe5b
--- /dev/null
+++ b/Swiften/Base/Shared.h
@@ -0,0 +1,22 @@
+/*
+ * 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>
+
+namespace Swift {
+	template<typename T>
+	class Shared {
+		public:
+			typedef boost::shared_ptr<T> ref;
+
+			template<typename X>
+			static boost::shared_ptr<T> cast(const X& from) {
+				return boost::dynamic_pointer_cast<T>(from);
+			}
+	};
+}
diff --git a/Swiften/Elements/Command.h b/Swiften/Elements/Command.h
index c802035..91ca915 100644
--- a/Swiften/Elements/Command.h
+++ b/Swiften/Elements/Command.h
@@ -7,13 +7,15 @@
 #pragma once
 
 #include "Swiften/Base/String.h"
+#include "Swiften/Base/Shared.h"
 #include "Swiften/Elements/Payload.h"
+#include "Swiften/Elements/Form.h"
 
 namespace Swift {
 	/**
 	 * Ad-Hoc Command (XEP-0050).
 	 */
-	class Command : public Payload {
+	class Command : public Payload, public Shared<Command> {
 		public:
 			enum Status {Executing, Completed, Canceled, NoStatus};
 			enum Action {Cancel, Execute, Complete, Prev, Next, NoAction};
@@ -29,26 +31,36 @@ namespace Swift {
 
 		public:
 			Command(const String& node, const String& sessionID, Status status) { constructor(node, sessionID, NoAction, status);}
-			Command(const String& node, const String& sessionID = "", Action action = Execute) { constructor(node, sessionID, action, NoStatus); }
+			Command(const String& node = "", const String& sessionID = "", Action action = Execute) { constructor(node, sessionID, action, NoStatus); }
 
 			const String& getNode() const { return node_; }
+			void setNode(const String& node) { node_ = node; }
+
 			const String& getSessionID() const { return sessionID_; }
-			Action getPerformedAction() const { return performedAction_; }
+			void setSessionID(const String& id) { sessionID_ = id; }
+
+			Action getAction() const { return action_; }
+			void setAction(Action action) { action_ = action; }
+
 			void setExecuteAction(Action action) { executeAction_ = action; }
 			Action getExecuteAction() const { return executeAction_; }
+
 			Status getStatus() const { return status_; }
+			void setStatus(Status status) { status_ = status; }
+
 			void addAvailableAction(Action action) { availableActions_.push_back(action); }
 			const std::vector<Action>& getAvailableActions() const { return availableActions_; }
 			void addNote(const Note& note) { notes_.push_back(note); }
 			const std::vector<Note>& getNotes() const { return notes_; }
-			boost::shared_ptr<Payload> getPayload() const { return payload_; }
-			void setPayload(boost::shared_ptr<Payload> payload) { payload_ = payload; }
+
+			Form::ref getForm() const { return form_; }
+			void setForm(Form::ref payload) { form_ = payload; }
 
 		private:
 			void constructor(const String& node, const String& sessionID, Action action, Status status) {
 				node_ = node;
 				sessionID_ = sessionID;
-				performedAction_ = action;
+				action_ = action;
 				status_ = status;
 				executeAction_ = NoAction;
 			}
@@ -56,11 +68,11 @@ namespace Swift {
 		private:
 			String node_;
 			String sessionID_;
-			Action performedAction_;
+			Action action_;
 			Status status_;
 			Action executeAction_;
 			std::vector<Action> availableActions_;
 			std::vector<Note> notes_;
-			boost::shared_ptr<Payload> payload_;
+			Form::ref form_;
 	};
 }
diff --git a/Swiften/Elements/Form.h b/Swiften/Elements/Form.h
index ed77d2b..34068ee 100644
--- a/Swiften/Elements/Form.h
+++ b/Swiften/Elements/Form.h
@@ -11,6 +11,7 @@
 #include "Swiften/Elements/Payload.h"
 #include "Swiften/Elements/FormField.h"
 #include "Swiften/Base/String.h"
+#include "Swiften/Base/Shared.h"
 #include "Swiften/JID/JID.h"
 
 namespace Swift {
@@ -19,7 +20,7 @@ namespace Swift {
 	 * For the relevant Fields, the parsers and serialisers protect the API user against
 	 * the strange multi-value instead of newline thing by transforming them.
 	 */
-	class Form : public Payload {
+	class Form : public Payload, public Shared<Form> {
 		public:
 			enum Type { FormType, SubmitType, CancelType, ResultType };
 
diff --git a/Swiften/Parser/PayloadParsers/CommandParser.cpp b/Swiften/Parser/PayloadParsers/CommandParser.cpp
new file mode 100644
index 0000000..4e80829
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CommandParser.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Parser/PayloadParsers/CommandParser.h"
+#include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/FormParser.h"
+
+namespace Swift {
+
+CommandParser::CommandParser() : level_(TopLevel), inNote_(false), inActions_(false), formParser_(0)  {
+	formParserFactory_ = new FormParserFactory();
+}
+
+CommandParser::~CommandParser() {
+	delete formParserFactory_;
+}
+
+void CommandParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+	++level_;
+	if (level_ == PayloadLevel) {
+		boost::optional<Command::Action> action = parseAction(attributes.getAttribute("action"));
+		if (action) {
+			getPayloadInternal()->setAction(*action);
+		}
+
+		String status = attributes.getAttribute("status");
+		if (status == "executing") {
+			getPayloadInternal()->setStatus(Command::Executing);
+		}
+		else if (status == "completed") {
+			getPayloadInternal()->setStatus(Command::Completed);
+		}
+		else if (status == "canceled") {
+			getPayloadInternal()->setStatus(Command::Canceled);
+		}
+
+		getPayloadInternal()->setNode(attributes.getAttribute("node"));
+		getPayloadInternal()->setSessionID(attributes.getAttribute("sessionid"));
+	}
+	else if (level_ == FormOrNoteOrActionsLevel) {
+		assert(!formParser_);
+		if (formParserFactory_->canParse(element, ns, attributes)) {
+			formParser_ = dynamic_cast<FormParser*>(formParserFactory_->createPayloadParser());
+			assert(formParser_);
+		}
+		else if (element == "note") {
+			inNote_ = true;
+			currentText_.clear();
+			String noteType = attributes.getAttribute("type");
+			if (noteType == "info") {
+				noteType_ = Command::Note::Info;
+			}
+			else if (noteType == "warn") {
+				noteType_ = Command::Note::Warn;
+			}
+			else if (noteType == "error") {
+				noteType_ = Command::Note::Error;
+			}
+			else {
+				noteType_ = Command::Note::Info;
+			}
+		}
+		else if (element == "actions") {
+			inActions_ = true;
+			boost::optional<Command::Action> action = parseAction(attributes.getAttribute("execute"));
+			if (action) {
+				getPayloadInternal()->setExecuteAction(*action);
+			}
+		}
+	}
+	else if (level_ == ActionsActionLevel) {
+	}
+
+	if (formParser_) {
+		formParser_->handleStartElement(element, ns, attributes);
+	}
+}
+
+void CommandParser::handleEndElement(const String& element, const String& ns) {
+	if (formParser_) {
+		formParser_->handleEndElement(element, ns);
+	}
+
+	if (level_ == FormOrNoteOrActionsLevel) {
+		if (formParser_) {
+			Form::ref form = Form::cast(formParser_->getPayload());
+			assert(form);
+			getPayloadInternal()->setForm(form);
+			delete formParser_;
+			formParser_ = 0;
+		}
+		else if (inNote_) {
+			inNote_ = false;
+			getPayloadInternal()->addNote(Command::Note(currentText_, noteType_));
+		}
+		else if (inActions_) {
+			inActions_ = false;
+		}
+	}
+	else if (level_ == ActionsActionLevel && inActions_) {
+		boost::optional<Command::Action> action = parseAction(element);
+		if (action) {
+			getPayloadInternal()->addAvailableAction(*action);
+		}
+	}
+	--level_;
+}
+
+void CommandParser::handleCharacterData(const String& data) {
+	if (formParser_) {
+		formParser_->handleCharacterData(data);
+	}
+	else {
+		currentText_ += data;
+	}
+}
+
+boost::optional<Command::Action> CommandParser::parseAction(const String& action) {
+	if (action == "execute") {
+		return Command::Execute;
+	}
+	else if (action == "cancel") {
+		return Command::Cancel;
+	}
+	else if (action == "prev") {
+		return Command::Prev;
+	}
+	else if (action == "next") {
+		return Command::Next;
+	}
+	else if (action == "complete") {
+		return Command::Complete;
+	}
+	return boost::optional<Command::Action>();
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/CommandParser.h b/Swiften/Parser/PayloadParsers/CommandParser.h
new file mode 100644
index 0000000..a682a80
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CommandParser.h
@@ -0,0 +1,45 @@
+/*
+ * 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/optional.hpp>
+
+#include "Swiften/Elements/Command.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+	class FormParserFactory;
+	class FormParser;
+
+	class CommandParser : public GenericPayloadParser<Command> {
+		public:
+			CommandParser();
+			~CommandParser();
+
+			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:
+			static boost::optional<Command::Action> parseAction(const String& action);
+
+		private:
+			enum Level { 
+				TopLevel = 0, 
+				PayloadLevel = 1,
+				FormOrNoteOrActionsLevel = 2,
+				ActionsActionLevel = 3
+			};
+			int level_;
+			bool inNote_;
+			bool inActions_;
+			Command::Note::Type noteType_;
+			FormParserFactory* formParserFactory_;
+			FormParser* formParser_;
+			String currentText_;
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/CommandParserFactory.h b/Swiften/Parser/PayloadParsers/CommandParserFactory.h
new file mode 100644
index 0000000..da2f484
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/CommandParserFactory.h
@@ -0,0 +1,29 @@
+/*
+ * 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 "Swiften/Parser/PayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/CommandParser.h"
+
+namespace Swift {
+	class PayloadParserFactoryCollection;
+
+	class CommandParserFactory : public PayloadParserFactory {
+		public:
+			CommandParserFactory() {
+			}
+
+			virtual bool canParse(const String& element, const String& ns, const AttributeMap&) const {
+				return ns == "http://jabber.org/protocol/commands" && element == "command";
+			}
+
+			virtual PayloadParser* createPayloadParser() {
+				return new CommandParser();
+			}
+
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index b115b10..ce6c9f8 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -25,6 +25,7 @@
 #include "Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/CommandParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/VCardParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h"
@@ -53,6 +54,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelsCatalogParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new FormParserFactory()));
+	factories_.push_back(shared_ptr<PayloadParserFactory>(new CommandParserFactory()));
 	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)));
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp
new file mode 100644
index 0000000..5f11718
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+#include "Swiften/Elements/Command.h"
+
+using namespace Swift;
+
+class CommandParserTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(CommandParserTest);
+		CPPUNIT_TEST(testParse);
+		CPPUNIT_TEST(testParse_Result);
+		CPPUNIT_TEST(testParse_Form);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testParse() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<command xmlns='http://jabber.org/protocol/commands' node='list' action='prev' sessionid='myid'/>"
+				));
+
+			Command::ref payload = parser.getPayload<Command>();
+			CPPUNIT_ASSERT_EQUAL(Command::Prev, payload->getAction());
+			CPPUNIT_ASSERT_EQUAL(String("list"), payload->getNode());
+			CPPUNIT_ASSERT_EQUAL(String("myid"), payload->getSessionID());
+		}
+
+		void testParse_Result() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed' sessionid='myid'>"
+					"<note type='warn'>Service 'httpd' has been configured.</note>"
+					"<note type='error'>I lied.</note>"
+					"<actions execute='next'>"
+						"<prev/>"
+						"<next/>"
+					"</actions>"
+				"</command>"
+				));
+
+			Command::ref payload = parser.getPayload<Command>();
+			CPPUNIT_ASSERT_EQUAL(Command::Completed, payload->getStatus());
+			std::vector<Command::Note> notes = payload->getNotes();
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(notes.size()));
+			CPPUNIT_ASSERT_EQUAL(Command::Note::Warn, notes[0].type);
+			CPPUNIT_ASSERT_EQUAL(String("Service 'httpd' has been configured."), notes[0].note);
+			CPPUNIT_ASSERT_EQUAL(Command::Note::Error, notes[1].type);
+			CPPUNIT_ASSERT_EQUAL(String("I lied."), notes[1].note);
+			std::vector<Command::Action> actions = payload->getAvailableActions();
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(actions.size()));
+			CPPUNIT_ASSERT_EQUAL(Command::Prev, actions[0]);
+			CPPUNIT_ASSERT_EQUAL(Command::Next, actions[1]);
+			CPPUNIT_ASSERT_EQUAL(Command::Next, payload->getExecuteAction());
+		}
+
+		void testParse_Form() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed'>"
+					"<x type=\"result\" xmlns=\"jabber:x:data\">"
+						"<title>Bot Configuration</title>"
+						"<instructions>Hello!</instructions>"
+						"<instructions>Fill out this form to configure your new bot!</instructions>"
+					"</x>"
+				"</command>"
+				));
+
+			Command::ref payload = parser.getPayload<Command>();
+			Form::ref form = payload->getForm();
+			CPPUNIT_ASSERT_EQUAL(String("Bot Configuration"), form->getTitle());
+			CPPUNIT_ASSERT_EQUAL(String("Hello!\nFill out this form to configure your new bot!"), form->getInstructions());
+			CPPUNIT_ASSERT_EQUAL(Form::ResultType, form->getType());
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CommandParserTest);
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
index e7d80e3..0d6e85e 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp
@@ -7,8 +7,8 @@
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
-#include "Swiften/Parser/PayloadParsers/FormParser.h"
 #include "Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h"
+#include "Swiften/Elements/Form.h"
 
 using namespace Swift;
 
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h
index 9ce0ac4..ee64181 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h
+++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h
@@ -12,6 +12,8 @@
 #include "Swiften/Parser/XMLParser.h"
 #include "Swiften/Parser/XMLParserClient.h"
 #include "Swiften/Parser/PlatformXMLParserFactory.h"
+#include "Swiften/Elements/Payload.h"
+#include "Swiften/Parser/PayloadParser.h"
 
 namespace Swift {
 	class PayloadsParserTester : public XMLParserClient {
@@ -52,6 +54,11 @@ namespace Swift {
 				return payloadParser->getPayload();
 			}
 
+			template<typename T>
+			boost::shared_ptr<T> getPayload() const {
+				return boost::dynamic_pointer_cast<T>(payloadParser->getPayload());
+			}
+
 		private:
 			XMLParser* xmlParser;
 			FullPayloadParserFactoryCollection factories;
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index 1826432..4efd343 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -24,6 +24,7 @@ sources = [
 		"PayloadParsers/DiscoItemsParser.cpp",
 		"PayloadParsers/ErrorParser.cpp",
 		"PayloadParsers/FormParser.cpp",
+		"PayloadParsers/CommandParser.cpp",
 		"PayloadParsers/FullPayloadParserFactoryCollection.cpp",
 		"PayloadParsers/PriorityParser.cpp",
 		"PayloadParsers/PrivateStorageParser.cpp",
diff --git a/Swiften/SConscript b/Swiften/SConscript
index f44d9a3..866baa9 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -167,6 +167,7 @@ if env["SCONS_STAGE"] == "build" :
 			File("Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp"),
 			File("Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp"),
 			File("Parser/PayloadParsers/UnitTest/FormParserTest.cpp"),
+			File("Parser/PayloadParsers/UnitTest/CommandParserTest.cpp"),
 			File("Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp"),
 			File("Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp"),
 			File("Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp"),
diff --git a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
index 3ac0c2c..eb45ca2 100644
--- a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp
@@ -13,10 +13,11 @@
 #include "Swiften/Serializer/XML/XMLTextNode.h"
 #include "Swiften/Serializer/XML/XMLRawTextNode.h"
 #include "Swiften/Serializer/PayloadSerializerCollection.h"
+#include "Swiften/Serializer/PayloadSerializers/FormSerializer.h"
 
 namespace Swift {
 
-CommandSerializer::CommandSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) {
+CommandSerializer::CommandSerializer() {
 }
 
 String CommandSerializer::serializePayload(boost::shared_ptr<Command> command)	const {
@@ -27,7 +28,7 @@ String CommandSerializer::serializePayload(boost::shared_ptr<Command> command)	c
 		commandElement.setAttribute("sessionid", command->getSessionID());
 	}
 
-	String action = actionToString(command->getPerformedAction());
+	String action = actionToString(command->getAction());
 	if (!action.isEmpty()) {
 		commandElement.setAttribute("action", action);
 	}
@@ -72,12 +73,9 @@ String CommandSerializer::serializePayload(boost::shared_ptr<Command> command)	c
 		commandElement.addNode(noteElement);
 	}
 
-	boost::shared_ptr<Payload> payload = command->getPayload();
-	if (payload) {
-		PayloadSerializer* serializer = serializers->getPayloadSerializer(payload);
-		if (serializer) {
-			commandElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(payload))));
-		}
+	Form::ref form = command->getForm();
+	if (form) {
+		commandElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(FormSerializer().serialize(form))));
 	}
 	return commandElement.serialize();
 }
diff --git a/Swiften/Serializer/PayloadSerializers/CommandSerializer.h b/Swiften/Serializer/PayloadSerializers/CommandSerializer.h
index 6a0c067..4b71aea 100644
--- a/Swiften/Serializer/PayloadSerializers/CommandSerializer.h
+++ b/Swiften/Serializer/PayloadSerializers/CommandSerializer.h
@@ -14,12 +14,11 @@ namespace Swift {
 
 	class CommandSerializer : public GenericPayloadSerializer<Command> {
 		public:
-			CommandSerializer(PayloadSerializerCollection* serializers);
+			CommandSerializer();
 
 			virtual String serializePayload(boost::shared_ptr<Command>)  const;
 
 		private:
-			PayloadSerializerCollection* serializers;
 			String actionToString(Command::Action action) const;
 	};
 }
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 04615a2..275cbf1 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -61,7 +61,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
 	serializers_.push_back(new DelaySerializer());
 	serializers_.push_back(new FormSerializer());
 	serializers_.push_back(new PrivateStorageSerializer(this));
-	serializers_.push_back(new CommandSerializer(this));
+	serializers_.push_back(new CommandSerializer());
 	foreach(PayloadSerializer* serializer, serializers_) {
 		addSerializer(serializer);
 	}
-- 
cgit v0.10.2-6-g49f6