diff options
author | Kevin Smith <git@kismith.co.uk> | 2011-09-21 12:25:27 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2011-09-23 16:47:57 (GMT) |
commit | f9c432ca127d6e7d87b49d2fbf6aace34bea0e06 (patch) | |
tree | d7f069d3c48cc3d768e770df614fe87ade6f3902 /Swiften/Parser | |
parent | 20d3385909a2f9d886e7e0781357b23474e9f8dc (diff) | |
download | swift-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.zip swift-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.tar.bz2 |
Add support for kicking people from MUCs.
This also introduces a new DOM-like parser structure, used for the
MUC parsers.
Partially
Resolves: #689
Diffstat (limited to 'Swiften/Parser')
-rw-r--r-- | Swiften/Parser/GenericPayloadTreeParser.cpp | 8 | ||||
-rw-r--r-- | Swiften/Parser/GenericPayloadTreeParser.h | 58 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp | 2 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp | 23 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h | 20 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCItemParser.cpp | 82 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCItemParser.h | 20 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp | 87 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h | 19 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp | 41 | ||||
-rw-r--r-- | Swiften/Parser/SConscript | 4 | ||||
-rw-r--r-- | Swiften/Parser/Tree/NullParserElement.h | 19 | ||||
-rw-r--r-- | Swiften/Parser/Tree/ParserElement.cpp | 72 | ||||
-rw-r--r-- | Swiften/Parser/Tree/ParserElement.h | 41 | ||||
-rw-r--r-- | Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp | 58 |
15 files changed, 464 insertions, 90 deletions
diff --git a/Swiften/Parser/GenericPayloadTreeParser.cpp b/Swiften/Parser/GenericPayloadTreeParser.cpp new file mode 100644 index 0000000..0e25cbc --- /dev/null +++ b/Swiften/Parser/GenericPayloadTreeParser.cpp @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Parser/GenericPayloadTreeParser.h> + diff --git a/Swiften/Parser/GenericPayloadTreeParser.h b/Swiften/Parser/GenericPayloadTreeParser.h new file mode 100644 index 0000000..0030af7 --- /dev/null +++ b/Swiften/Parser/GenericPayloadTreeParser.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <deque> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Parser/Tree/ParserElement.h> +#include <Swiften/Parser/Tree/NullParserElement.h> + +#include <iostream> + +namespace Swift { + + + /** + * Generic parser offering something a bit like a DOM to work with. + */ + template<typename PAYLOAD_TYPE> + class GenericPayloadTreeParser : public GenericPayloadParser<PAYLOAD_TYPE> { + public: + virtual void handleStartElement(const std::string& element, const std::string& xmlns, const AttributeMap& attributes) { + //std::cerr << element << ", " << xmlns << ", " << attributes.getEntries().size(); + if (!root_) { + root_ = boost::make_shared<ParserElement>(element, xmlns, attributes); + elementStack_.push_back(root_); + } else { + ParserElement::ref current = *elementStack_.rbegin(); + elementStack_.push_back(current->addChild(element, xmlns, attributes)); + } + } + + virtual void handleEndElement(const std::string& /*element*/, const std::string&) { + elementStack_.pop_back(); + if (elementStack_.empty()) { + handleTree(root_); + } + } + + virtual void handleCharacterData(const std::string& data) { + ParserElement::ref current = *elementStack_.rbegin(); + current->appendCharacterData(data); + } + + virtual void handleTree(ParserElement::ref root) = 0; + + private: + std::deque<ParserElement::ref> elementStack_; + ParserElement::ref root_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index e9c49ee..1b59f6f 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -44,6 +44,7 @@ #include <Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h> #include <Swiften/Parser/PayloadParsers/DelayParser.h> #include <Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h> #include <Swiften/Parser/PayloadParsers/NicknameParserFactory.h> #include <Swiften/Parser/PayloadParsers/ReplaceParser.h> #include <Swiften/Parser/PayloadParsers/LastParser.h> @@ -88,6 +89,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { factories_.push_back(shared_ptr<PayloadParserFactory>(new PrivateStorageParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new ChatStateParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new MUCUserPayloadParserFactory())); + factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<MUCAdminPayloadParser>("query", "http://jabber.org/protocol/muc#admin"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new NicknameParserFactory())); foreach(shared_ptr<PayloadParserFactory> factory, factories_) { addFactory(factory.get()); diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp new file mode 100644 index 0000000..137ead4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Elements/MUCOccupant.h> + +namespace Swift { + +void MUCAdminPayloadParser::handleTree(ParserElement::ref root) { + foreach (ParserElement::ref itemElement, root->getChildren("item", "http://jabber.org/protocol/muc#admin")) { + MUCItem item = MUCItemParser::itemFromTree(itemElement); + getPayloadInternal()->addItem(item); + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h new file mode 100644 index 0000000..dfa26da --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 Kevin Smith + * 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/MUCAdminPayload.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> +#include <Swiften/Parser/PayloadParsers/MUCItemParser.h> + +namespace Swift { + class MUCAdminPayloadParser : public GenericPayloadTreeParser<MUCAdminPayload> { + public: + virtual void handleTree(ParserElement::ref root); + }; +} diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.cpp b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp new file mode 100644 index 0000000..2eb9997 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MUCItemParser.h> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Elements/MUCOccupant.h> + +#include <cassert> +#include <iostream> + +namespace Swift { + +MUCItem MUCItemParser::itemFromTree(ParserElement::ref root) { + MUCItem item; + std::string affiliation = root->getAttributes().getAttribute("affiliation"); + std::string role = root->getAttributes().getAttribute("role"); + std::string nick = root->getAttributes().getAttribute("nick"); + std::string jid = root->getAttributes().getAttribute("jid"); + item.affiliation = parseAffiliation(affiliation); + item.role = parseRole(role); + if (!jid.empty()) { + item.realJID = JID(jid); + } + if (!nick.empty()) { + item.nick = nick; + } + std::string xmlns = root->getNamespace(); + std::string reason = root->getChild("reason", xmlns)->getText(); + std::string actor = root->getChild("actor", xmlns)->getAttributes().getAttribute("jid"); + if (!reason.empty()) { + item.reason = reason; + } + if (!actor.empty()) { + item.actor = JID(actor); + } + + return item; +} + +boost::optional<MUCOccupant::Role> MUCItemParser::parseRole(const std::string& roleString) { + if (roleString == "moderator") { + return MUCOccupant::Moderator; + } + if (roleString == "participant") { + return MUCOccupant::Participant; + } + if (roleString == "visitor") { + return MUCOccupant::Visitor; + } + if (roleString == "none") { + return MUCOccupant::NoRole; + } + return boost::optional<MUCOccupant::Role>(); +} + +boost::optional<MUCOccupant::Affiliation> MUCItemParser::parseAffiliation(const std::string& affiliationString) { + if (affiliationString == "owner") { + return MUCOccupant::Owner; + } + if (affiliationString == "admin") { + return MUCOccupant::Admin; + } + if (affiliationString == "member") { + return MUCOccupant::Member; + } + if (affiliationString == "outcast") { + return MUCOccupant::Outcast; + } + if (affiliationString == "none") { + return MUCOccupant::NoAffiliation; + } + return boost::optional<MUCOccupant::Affiliation>(); +} + +} + + diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.h b/Swiften/Parser/PayloadParsers/MUCItemParser.h new file mode 100644 index 0000000..a0ea060 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCItemParser.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/MUCItem.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class MUCItemParser { + public: + static MUCItem itemFromTree(ParserElement::ref root); + private: + static boost::optional<MUCOccupant::Role> parseRole(const std::string& itemString); + static boost::optional<MUCOccupant::Affiliation> parseAffiliation(const std::string& statusString); + }; +} diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp index bd81b88..71ae571 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp @@ -8,87 +8,24 @@ #include <boost/lexical_cast.hpp> +#include <Swiften/Base/foreach.h> #include <Swiften/Elements/MUCOccupant.h> -#include <cassert> -#include <iostream> - namespace Swift { -MUCUserPayloadParser::MUCUserPayloadParser() : level(TopLevel) { -} - -void MUCUserPayloadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == ItemLevel) { - if (element == "item") { - MUCUserPayload::Item item; - std::string affiliation = attributes.getAttribute("affiliation"); - std::string role = attributes.getAttribute("role"); - std::string nick = attributes.getAttribute("nick"); - std::string jid = attributes.getAttribute("jid"); - item.affiliation = parseAffiliation(affiliation); - item.role = parseRole(role); - if (!jid.empty()) { - item.realJID = JID(jid); - } - if (!nick.empty()) { - item.nick = nick; - } - getPayloadInternal()->addItem(item); - } else if (element == "status") { - MUCUserPayload::StatusCode status; - try { - status.code = boost::lexical_cast<int>(attributes.getAttribute("code").c_str()); - getPayloadInternal()->addStatusCode(status); - } catch (boost::bad_lexical_cast&) { - } +void MUCUserPayloadParser::handleTree(ParserElement::ref root) { + foreach (ParserElement::ref itemElement, root->getChildren("item", "http://jabber.org/protocol/muc#user")) { + MUCItem item = MUCItemParser::itemFromTree(itemElement); + getPayloadInternal()->addItem(item); + } + foreach (ParserElement::ref statusElement, root->getChildren("item", "http://jabber.org/protocol/muc#user")) { + MUCUserPayload::StatusCode status; + try { + status.code = boost::lexical_cast<int>(statusElement->getAttributes().getAttribute("code").c_str()); + getPayloadInternal()->addStatusCode(status); + } catch (boost::bad_lexical_cast&) { } } - ++level; -} - -MUCOccupant::Role MUCUserPayloadParser::parseRole(const std::string& roleString) const { - if (roleString == "moderator") { - return MUCOccupant::Moderator; - } - if (roleString == "participant") { - return MUCOccupant::Participant; - } - if (roleString == "visitor") { - return MUCOccupant::Visitor; - } - if (roleString == "none") { - return MUCOccupant::NoRole; - } - return MUCOccupant::NoRole; -} - -MUCOccupant::Affiliation MUCUserPayloadParser::parseAffiliation(const std::string& affiliationString) const { - if (affiliationString == "owner") { - return MUCOccupant::Owner; - } - if (affiliationString == "admin") { - return MUCOccupant::Admin; - } - if (affiliationString == "member") { - return MUCOccupant::Member; - } - if (affiliationString == "outcast") { - return MUCOccupant::Outcast; - } - if (affiliationString == "none") { - return MUCOccupant::NoAffiliation; - } - return MUCOccupant::NoAffiliation; -} - - -void MUCUserPayloadParser::handleEndElement(const std::string& /*element*/, const std::string&) { - --level; -} - -void MUCUserPayloadParser::handleCharacterData(const std::string& /*data*/) { - } } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h index b819905..e020127 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h @@ -9,23 +9,12 @@ #include <boost/optional.hpp> #include <Swiften/Elements/MUCUserPayload.h> -#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> +#include <Swiften/Parser/PayloadParsers/MUCItemParser.h> namespace Swift { - class MUCUserPayloadParser : public GenericPayloadParser<MUCUserPayload> { + class MUCUserPayloadParser : public GenericPayloadTreeParser<MUCUserPayload> { public: - MUCUserPayloadParser(); - - virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes); - virtual void handleEndElement(const std::string& element, const std::string&); - virtual void handleCharacterData(const std::string& data); - MUCOccupant::Role parseRole(const std::string& itemString) const; - MUCOccupant::Affiliation parseAffiliation(const std::string& statusString) const; - private: - enum Level { - TopLevel = 0, - ItemLevel = 1 - }; - int level; + virtual void handleTree(ParserElement::ref root); }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp new file mode 100644 index 0000000..0648f58 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 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/Parser/PayloadParsers/MUCAdminPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class MUCAdminPayloadParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(MUCAdminPayloadParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + MUCAdminPayloadParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>")); + + MUCAdminPayload::ref payload = boost::dynamic_pointer_cast<MUCAdminPayload>(parser.getPayload()); + MUCItem item = payload->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get()); + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get()); + CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get()); + CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MUCAdminPayloadParserTest); + + + diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 17505f1..b9fcebb 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -14,6 +14,7 @@ sources = [ "CompressParser.cpp", "ElementParser.cpp", "IQParser.cpp", + "GenericPayloadTreeParser.cpp", "MessageParser.cpp", "PayloadParser.cpp", "StanzaAckParser.cpp", @@ -51,6 +52,8 @@ sources = [ "PayloadParsers/VCardUpdateParser.cpp", "PayloadParsers/DelayParser.cpp", "PayloadParsers/MUCUserPayloadParser.cpp", + "PayloadParsers/MUCAdminPayloadParser.cpp", + "PayloadParsers/MUCItemParser.cpp", "PayloadParsers/NicknameParser.cpp", "PayloadParsers/ReplaceParser.cpp", "PayloadParsers/LastParser.cpp", @@ -63,6 +66,7 @@ sources = [ "StreamManagementEnabledParser.cpp", "StreamResumeParser.cpp", "StreamResumedParser.cpp", + "Tree/ParserElement.cpp", "XMLParser.cpp", "XMLParserClient.cpp", "XMLParserFactory.cpp", diff --git a/Swiften/Parser/Tree/NullParserElement.h b/Swiften/Parser/Tree/NullParserElement.h new file mode 100644 index 0000000..93c0662 --- /dev/null +++ b/Swiften/Parser/Tree/NullParserElement.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> +#include <Swiften/Parser/Tree/ParserElement.h> + +namespace Swift { + + class NullParserElement : public ParserElement { + public: + NullParserElement() : ParserElement("", "", AttributeMap()) {} + virtual operator bool() {return false;}; + }; +} diff --git a/Swiften/Parser/Tree/ParserElement.cpp b/Swiften/Parser/Tree/ParserElement.cpp new file mode 100644 index 0000000..c851b41 --- /dev/null +++ b/Swiften/Parser/Tree/ParserElement.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + + +#include <Swiften/Parser/Tree/ParserElement.h> +#include <Swiften/Parser/Tree/NullParserElement.h> + +#include <iostream> + +namespace Swift{ + +ParserElement::ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) : name_(name), xmlns_(xmlns), attributes_(attributes) { + +} + +ParserElement::~ParserElement() { + +} + +ParserElement::operator bool() { + return true; +} + +ParserElement::ref ParserElement::addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) { + ParserElement::ref child = boost::make_shared<ParserElement>(name, xmlns, attributes); + children_.push_back(child); + return child; +} + +void ParserElement::appendCharacterData(const std::string& data) { + text_ += data; +} + +std::string ParserElement::getText() { + return text_; +} + +std::string ParserElement::getName() { + return name_; +} + +std::string ParserElement::getNamespace() { + return xmlns_; +} + +struct DoesntMatch { + public: + DoesntMatch(const std::string& tagName, const std::string& ns) : tagName(tagName), ns(ns) {} + bool operator()(ParserElement::ref element) { return element->getName() != tagName || element->getNamespace() != ns; } + private: + std::string tagName; + std::string ns; +}; + + +std::vector<ParserElement::ref> ParserElement::getChildren(const std::string& name, const std::string& xmlns) { + std::vector<ParserElement::ref> result; + std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), DoesntMatch(name, xmlns)); + return result; +} + +ParserElement::ref ParserElement::getChild(const std::string& name, const std::string& xmlns) { + std::vector<ParserElement::ref> results = getChildren(name, xmlns); + boost::shared_ptr<NullParserElement> nullParser = boost::make_shared<NullParserElement>(); + ParserElement::ref result = results.empty() ? boost::dynamic_pointer_cast<ParserElement>(nullParser) : results[0]; + return result; +} + +} diff --git a/Swiften/Parser/Tree/ParserElement.h b/Swiften/Parser/Tree/ParserElement.h new file mode 100644 index 0000000..ddf67fa --- /dev/null +++ b/Swiften/Parser/Tree/ParserElement.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + + +#pragma once + +#include <string> +#include <vector> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Parser/AttributeMap.h> +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +namespace Swift { +class ParserElement { + public: + typedef boost::shared_ptr<ParserElement> ref; + ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); + virtual ~ParserElement(); + virtual operator bool(); + ParserElement::ref addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); + void appendCharacterData(const std::string& data); + std::string getText(); + std::string getName(); + std::string getNamespace(); + std::vector<ParserElement::ref> getChildren(const std::string& name, const std::string& xmlns); + ParserElement::ref getChild(const std::string& name, const std::string& xmlns); + const AttributeMap& getAttributes() const {return attributes_;} + private: + std::vector<ParserElement::ref> children_; + std::string name_; + std::string xmlns_; + AttributeMap attributes_; + std::string text_; + +}; + +} diff --git a/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp new file mode 100644 index 0000000..d095afc --- /dev/null +++ b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 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/Parser/GenericPayloadTreeParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h> +#include <Swiften/Elements/RawXMLPayload.h> + +using namespace Swift; + +class GenericPayloadTreeParserTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(GenericPayloadTreeParserTest); + CPPUNIT_TEST(testTree); + CPPUNIT_TEST_SUITE_END(); + + public: + void testTree() { + MyParser testling; + + std::string data = "<topLevel xmlns='urn:test:top'><firstLevelInheritedEmpty/><firstLevelInherited><secondLevelMultiChildren num='1'/><secondLevelMultiChildren num='2'/></firstLevelInherited><firstLevelNS xmlns='urn:test:first'/></topLevel>"; + + PayloadParserTester tester(&testling); + tester.parse(data); + + ParserElement::ref tree = testling.tree; + + CPPUNIT_ASSERT_EQUAL(std::string("topLevel"), tree->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("urn:test:top"), tree->getNamespace()); + CPPUNIT_ASSERT(tree->getChild("firstLevelInheritedEmpty", "urn:test:top")); + CPPUNIT_ASSERT(!*tree->getChild("firstLevelInheritedEmpty", "")); + CPPUNIT_ASSERT(tree->getChild("firstLevelInherited", "urn:test:top")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top").size()); + CPPUNIT_ASSERT_EQUAL(std::string("1"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[0]->getAttributes().getAttribute("num")); + CPPUNIT_ASSERT_EQUAL(std::string("2"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[1]->getAttributes().getAttribute("num")); + CPPUNIT_ASSERT(tree->getChild("firstLevelNS", "urn:test:first")); + } + + private: + + + class MyParser : public GenericPayloadTreeParser<RawXMLPayload> + { + public: + virtual ~MyParser() {} + virtual void handleTree(ParserElement::ref root) { + tree = root; + } + ParserElement::ref tree; + }; + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(GenericPayloadTreeParserTest); |