diff options
author | Remko Tronçon <git@el-tramo.be> | 2013-08-22 21:07:51 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2013-08-23 08:02:12 (GMT) |
commit | 00284e5f4445a7bbab482196901c5927ea7d5488 (patch) | |
tree | f2ca6e0c51632a8aa5a7a884f3b312bacc3a2fb0 | |
parent | 54da0a4c0cceae947afbde586a97d1cc60c50ed8 (diff) | |
download | swift-00284e5f4445a7bbab482196901c5927ea7d5488.zip swift-00284e5f4445a7bbab482196901c5927ea7d5488.tar.bz2 |
FormField element refactoring.
This should make FormField easier to use.
Change-Id: Ia5eeedcdb673e2fe5e38fd23d5ab00970178bc44
21 files changed, 379 insertions, 503 deletions
diff --git a/Swift/QtUI/QtFormResultItemModel.cpp b/Swift/QtUI/QtFormResultItemModel.cpp index b052334..8920128 100644 --- a/Swift/QtUI/QtFormResultItemModel.cpp +++ b/Swift/QtUI/QtFormResultItemModel.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include "QtFormResultItemModel.h" #include <boost/algorithm/string/join.hpp> @@ -69,15 +75,16 @@ const std::string QtFormResultItemModel::getFieldValue(const Form::FormItem& ite foreach(FormField::ref field, item) { if (field->getName() == name) { std::string delimiter = ""; - if (boost::dynamic_pointer_cast<TextMultiFormField>(field)) { + if (field->getType() == FormField::TextMultiType) { delimiter = "\n"; - } else if (boost::dynamic_pointer_cast<JIDMultiFormField>(field)) { + } + else if (field->getType() == FormField::JIDMultiType) { delimiter = ", "; - } else if (boost::dynamic_pointer_cast<ListMultiFormField>(field)) { + } + else if (field->getType() == FormField::ListMultiType) { delimiter = ", "; } - - return boost::algorithm::join(field->getRawValues(), delimiter); + return boost::algorithm::join(field->getValues(), delimiter); } } diff --git a/Swift/QtUI/QtFormWidget.cpp b/Swift/QtUI/QtFormWidget.cpp index 4216863..9b213cf 100644 --- a/Swift/QtUI/QtFormWidget.cpp +++ b/Swift/QtUI/QtFormWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,6 +17,8 @@ #include <Swift/QtUI/QtSwiftUtil.h> #include <Swiften/Base/foreach.h> +#include <boost/algorithm/string/join.hpp> +#include <boost/smart_ptr/make_shared.hpp> namespace Swift { @@ -54,18 +56,16 @@ QtFormWidget::~QtFormWidget() { QListWidget* QtFormWidget::createList(FormField::ref field) { QListWidget* listWidget = new QListWidget(this); listWidget->setSortingEnabled(false); - listWidget->setSelectionMode(boost::dynamic_pointer_cast<ListMultiFormField>(field) ? QAbstractItemView::MultiSelection : QAbstractItemView::SingleSelection); - boost::shared_ptr<ListMultiFormField> listMultiField = boost::dynamic_pointer_cast<ListMultiFormField>(field); - boost::shared_ptr<ListSingleFormField> listSingleField = boost::dynamic_pointer_cast<ListSingleFormField>(field); + listWidget->setSelectionMode(field->getType() == FormField::ListMultiType ? QAbstractItemView::MultiSelection : QAbstractItemView::SingleSelection); std::vector<bool> selected; foreach (FormField::Option option, field->getOptions()) { listWidget->addItem(option.label.c_str()); - if (listSingleField) { - selected.push_back(option.value == listSingleField->getValue()); + if (field->getType() == FormField::ListMultiType) { + selected.push_back(!field->getValues().empty() && option.value == field->getValues()[0]); } - else if (listMultiField) { + else if (field->getType() == FormField::ListMultiType) { std::string text = option.value; - selected.push_back(std::find(listMultiField->getValue().begin(), listMultiField->getValue().end(), text) != listMultiField->getValue().end()); + selected.push_back(std::find(field->getValues().begin(), field->getValues().end(), text) != field->getValues().end()); } } @@ -78,67 +78,47 @@ QListWidget* QtFormWidget::createList(FormField::ref field) { QWidget* QtFormWidget::createWidget(FormField::ref field) { QWidget* widget = NULL; - boost::shared_ptr<BooleanFormField> booleanField = boost::dynamic_pointer_cast<BooleanFormField>(field); - if (booleanField) { + if (field->getType() == FormField::BooleanType) { QCheckBox* checkWidget = new QCheckBox(this); - checkWidget->setCheckState(booleanField->getValue() ? Qt::Checked : Qt::Unchecked); + checkWidget->setCheckState(field->getBoolValue() ? Qt::Checked : Qt::Unchecked); widget = checkWidget; } - boost::shared_ptr<FixedFormField> fixedField = boost::dynamic_pointer_cast<FixedFormField>(field); - if (fixedField) { - QString value = fixedField->getValue().c_str(); + if (field->getType() == FormField::FixedType) { + QString value = field->getFixedValue().c_str(); widget = new QLabel(value, this); } - boost::shared_ptr<ListSingleFormField> listSingleField = boost::dynamic_pointer_cast<ListSingleFormField>(field); - if (listSingleField) { + if (field->getType() == FormField::ListSingleType) { widget = createList(field); } - boost::shared_ptr<TextMultiFormField> textMultiField = boost::dynamic_pointer_cast<TextMultiFormField>(field); - if (textMultiField) { - QString value = textMultiField->getValue().c_str(); + if (field->getType() == FormField::TextMultiType) { + QString value = field->getTextMultiValue().c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(value); widget = textWidget; } - boost::shared_ptr<TextPrivateFormField> textPrivateField = boost::dynamic_pointer_cast<TextPrivateFormField>(field); - if (textPrivateField) { - QString value = textPrivateField->getValue().c_str(); + if (field->getType() == FormField::TextPrivateType) { + QString value = field->getTextPrivateValue().c_str(); QLineEdit* lineWidget = new QLineEdit(value, this); lineWidget->setEchoMode(QLineEdit::Password); widget = lineWidget; } - boost::shared_ptr<TextSingleFormField> textSingleField = boost::dynamic_pointer_cast<TextSingleFormField>(field); - if (textSingleField) { - QString value = textSingleField->getValue().c_str(); + if (field->getType() == FormField::TextSingleType) { + QString value = field->getTextSingleValue().c_str(); widget = new QLineEdit(value, this); } - boost::shared_ptr<JIDSingleFormField> jidSingleField = boost::dynamic_pointer_cast<JIDSingleFormField>(field); - if (jidSingleField) { - QString value = jidSingleField->getValue().toString().c_str(); + if (field->getType() == FormField::JIDSingleType) { + QString value = field->getJIDSingleValue().toString().c_str(); widget = new QLineEdit(value, this); } - boost::shared_ptr<JIDMultiFormField> jidMultiField = boost::dynamic_pointer_cast<JIDMultiFormField>(field); - if (jidMultiField) { - QString text; - bool prev = false; - foreach (JID line, jidMultiField->getValue()) { - if (prev) { - text += "\n"; - } - prev = true; - text += line.toString().c_str(); - } + if (field->getType() == FormField::JIDMultiType) { + QString text = boost::join(field->getValues(), "\n").c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(text); widget = textWidget; } - boost::shared_ptr<ListMultiFormField> listMultiField = boost::dynamic_pointer_cast<ListMultiFormField>(field); - if (listMultiField) { + if (field->getType() == FormField::ListMultiType) { widget = createList(field); } - boost::shared_ptr<HiddenFormField> hiddenField = boost::dynamic_pointer_cast<HiddenFormField>(field); - if (hiddenField) { - } fields_[field->getName()] = widget; return widget; } @@ -146,101 +126,51 @@ QWidget* QtFormWidget::createWidget(FormField::ref field) { Form::ref QtFormWidget::getCompletedForm() { Form::ref result(new Form(Form::SubmitType)); foreach (boost::shared_ptr<FormField> field, form_->getFields()) { - boost::shared_ptr<FormField> resultField; - boost::shared_ptr<BooleanFormField> booleanField = boost::dynamic_pointer_cast<BooleanFormField>(field); - if (booleanField) { - resultField = FormField::ref(BooleanFormField::create(qobject_cast<QCheckBox*>(fields_[field->getName()])->checkState() == Qt::Checked)); + boost::shared_ptr<FormField> resultField = boost::make_shared<FormField>(field->getType()); + if (field->getType() == FormField::BooleanType) { + resultField->setBoolValue(qobject_cast<QCheckBox*>(fields_[field->getName()])->checkState() == Qt::Checked); } - boost::shared_ptr<FixedFormField> fixedField = boost::dynamic_pointer_cast<FixedFormField>(field); - if (fixedField) { - resultField = FormField::ref(FixedFormField::create(fixedField->getValue())); + if (field->getType() == FormField::FixedType || field->getType() == FormField::HiddenType) { + resultField->addValue(field->getValues().empty() ? "" : field->getValues()[0]); } - boost::shared_ptr<ListSingleFormField> listSingleField = boost::dynamic_pointer_cast<ListSingleFormField>(field); - if (listSingleField) { + if (field->getType() == FormField::ListSingleType) { QListWidget* listWidget = qobject_cast<QListWidget*>(fields_[field->getName()]); if (listWidget->selectedItems().size() > 0) { int i = listWidget->row(listWidget->selectedItems()[0]); - resultField = FormField::ref(ListSingleFormField::create(field->getOptions()[i].value)); - } - else { - resultField = FormField::ref(ListSingleFormField::create()); + resultField->addValue(field->getOptions()[i].value); } } - boost::shared_ptr<TextMultiFormField> textMultiField = boost::dynamic_pointer_cast<TextMultiFormField>(field); - if (textMultiField) { + if (field->getType() == FormField::TextMultiType) { QTextEdit* widget = qobject_cast<QTextEdit*>(fields_[field->getName()]); QString string = widget->toPlainText(); - if (string.isEmpty()) { - resultField = FormField::ref(TextMultiFormField::create()); - } - else { - resultField = FormField::ref(TextMultiFormField::create(Q2PSTRING(string))); - } - } - boost::shared_ptr<TextPrivateFormField> textPrivateField = boost::dynamic_pointer_cast<TextPrivateFormField>(field); - if (textPrivateField) { - QLineEdit* widget = qobject_cast<QLineEdit*>(fields_[field->getName()]); - QString string = widget->text(); - if (string.isEmpty()) { - resultField = FormField::ref(TextPrivateFormField::create()); - } - else { - resultField = FormField::ref(TextPrivateFormField::create(Q2PSTRING(string))); + if (!string.isEmpty()) { + resultField->setTextMultiValue(Q2PSTRING(string)); } } - boost::shared_ptr<TextSingleFormField> textSingleField = boost::dynamic_pointer_cast<TextSingleFormField>(field); - if (textSingleField) { + if (field->getType() == FormField::TextPrivateType || field->getType() == FormField::TextSingleType || field->getType() == FormField::JIDSingleType) { QLineEdit* widget = qobject_cast<QLineEdit*>(fields_[field->getName()]); QString string = widget->text(); - if (string.isEmpty()) { - resultField = FormField::ref(TextSingleFormField::create()); - } - else { - resultField = FormField::ref(TextSingleFormField::create(Q2PSTRING(string))); + if (!string.isEmpty()) { + resultField->addValue(Q2PSTRING(string)); } } - boost::shared_ptr<JIDSingleFormField> jidSingleField = boost::dynamic_pointer_cast<JIDSingleFormField>(field); - if (jidSingleField) { - QLineEdit* widget = qobject_cast<QLineEdit*>(fields_[field->getName()]); - QString string = widget->text(); - JID jid(Q2PSTRING(string)); - if (string.isEmpty()) { - resultField = FormField::ref(JIDSingleFormField::create()); - } - else { - resultField = FormField::ref(JIDSingleFormField::create(jid)); - } - } - boost::shared_ptr<JIDMultiFormField> jidMultiField = boost::dynamic_pointer_cast<JIDMultiFormField>(field); - if (jidMultiField) { + if (field->getType() == FormField::JIDMultiType) { QTextEdit* widget = qobject_cast<QTextEdit*>(fields_[field->getName()]); QString string = widget->toPlainText(); - if (string.isEmpty()) { - resultField = FormField::ref(JIDMultiFormField::create()); - } - else { + if (!string.isEmpty()) { QStringList lines = string.split("\n"); - std::vector<JID> value; foreach (QString line, lines) { - value.push_back(JID(Q2PSTRING(line))); + resultField->addValue(Q2PSTRING(line)); } - resultField = FormField::ref(JIDMultiFormField::create(value)); } } - boost::shared_ptr<ListMultiFormField> listMultiField = boost::dynamic_pointer_cast<ListMultiFormField>(field); - if (listMultiField) { + if (field->getType() == FormField::ListMultiType) { QListWidget* listWidget = qobject_cast<QListWidget*>(fields_[field->getName()]); - std::vector<std::string> values; foreach (QListWidgetItem* item, listWidget->selectedItems()) { - values.push_back(field->getOptions()[listWidget->row(item)].value); + resultField->addValue(field->getOptions()[listWidget->row(item)].value); } - resultField = FormField::ref(ListMultiFormField::create(values)); - } - boost::shared_ptr<HiddenFormField> hiddenField = boost::dynamic_pointer_cast<HiddenFormField>(field); - if (hiddenField) { - resultField = FormField::ref(HiddenFormField::create(hiddenField->getValue())); } - resultField->setName(field->getName()); + field->setName(field->getName()); result->addField(resultField); } return result; diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp index 02b238e..73514fd 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -179,12 +179,12 @@ JID QtUserSearchWindow::getContactJID() const { Form::FormItem item = dynamic_cast<QtFormResultItemModel*>(model_)->getForm()->getItems().at(row); JID fallbackJid; foreach(FormField::ref field, item) { - if (boost::dynamic_pointer_cast<JIDSingleFormField>(field)) { - jid = JID(field->getRawValues().at(0)); + if (field->getType() == FormField::JIDSingleType) { + jid = JID(field->getJIDSingleValue()); break; } if (field->getName() == "jid") { - fallbackJid = field->getRawValues().at(0); + fallbackJid = field->getValues()[0]; } } if (!jid.isValid()) { diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp index cb93182..4332f76 100644 --- a/Swiften/Disco/CapsInfoGenerator.cpp +++ b/Swiften/Disco/CapsInfoGenerator.cpp @@ -49,7 +49,7 @@ CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { continue; } serializedCaps += field->getName() + "<"; - std::vector<std::string> values(field->getRawValues()); + std::vector<std::string> values(field->getValues()); std::sort(values.begin(), values.end()); foreach(const std::string& value, values) { serializedCaps += value + "<"; diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp index a1b1a7b..67d27c0 100644 --- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp +++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp @@ -51,32 +51,25 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture { discoInfo.addFeature("http://jabber.org/protocol/muc"); Form::ref extension(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("urn:xmpp:dataforms:softwareinfo"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); field->setName("FORM_TYPE"); extension->addField(field); - std::vector<std::string> ipVersions; - ipVersions.push_back("ipv6"); - ipVersions.push_back("ipv4"); - field = ListMultiFormField::create(ipVersions); - field->addRawValue("ipv6"); - field->addRawValue("ipv4"); + field = boost::make_shared<FormField>(FormField::ListMultiType); + field->addValue("ipv6"); + field->addValue("ipv4"); field->setName("ip_version"); extension->addField(field); - field = TextSingleFormField::create("Psi"); - field->addRawValue("Psi"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Psi"); field->setName("software"); extension->addField(field); - field = TextSingleFormField::create("0.11"); - field->addRawValue("0.11"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "0.11"); field->setName("software_version"); extension->addField(field); - field = TextSingleFormField::create("Mac"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Mac"); field->setName("os"); - field->addRawValue("Mac"); extension->addField(field); - field = TextSingleFormField::create("10.5.1"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); field->setName("os_version"); - field->addRawValue("10.5.1"); extension->addField(field); discoInfo.addExtension(extension); diff --git a/Swiften/Elements/Form.cpp b/Swiften/Elements/Form.cpp index cf9ecf6..c4ae410 100644 --- a/Swiften/Elements/Form.cpp +++ b/Swiften/Elements/Form.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,8 +11,10 @@ namespace Swift { std::string Form::getFormType() const { FormField::ref field = getField("FORM_TYPE"); - boost::shared_ptr<HiddenFormField> f = boost::dynamic_pointer_cast<HiddenFormField>(field); - return (f ? f->getValue() : ""); + if (field && field->getType() == FormField::HiddenType) { + return field->getValues().empty() ? "" : field->getValues()[0]; + } + return ""; } FormField::ref Form::getField(const std::string& name) const { diff --git a/Swiften/Elements/FormField.cpp b/Swiften/Elements/FormField.cpp new file mode 100644 index 0000000..27ced82 --- /dev/null +++ b/Swiften/Elements/FormField.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/FormField.h> + +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/classification.hpp> + +using namespace Swift; + +FormField::~FormField() { +} + +std::string FormField::getTextMultiValue() const { + assert(type == TextMultiType || type == UnknownType); + return boost::algorithm::join(values, "\n"); +} + +void FormField::setTextMultiValue(const std::string& value) { + assert(type == TextMultiType || type == UnknownType); + values.clear(); + boost::split(values, value, boost::is_any_of("\n")); +} + +void FormField::setBoolValue(bool b) { + assert(type == BooleanType || type == UnknownType); + values.clear(); + values.push_back(b ? "1" : "0"); +} diff --git a/Swiften/Elements/FormField.h b/Swiften/Elements/FormField.h index fbd1ebe..26e70bb 100644 --- a/Swiften/Elements/FormField.h +++ b/Swiften/Elements/FormField.h @@ -1,12 +1,9 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -// FIXME: We currently keep 2 values: the raw values, and the actual value. -// We should only store the raw values, and deduce the actual values from this - #pragma once #include <vector> @@ -20,7 +17,25 @@ namespace Swift { public: typedef boost::shared_ptr<FormField> ref; - virtual ~FormField() {} + enum Type { + UnknownType, + BooleanType, + FixedType, + HiddenType, + ListSingleType, + TextMultiType, + TextPrivateType, + TextSingleType, + JIDSingleType, + JIDMultiType, + ListMultiType + }; + + FormField(Type type = UnknownType) : type(type), required(false) {} + FormField(Type type, const std::string& value) : type(type), required(false) { + addValue(value); + } + virtual ~FormField(); struct Option { Option(const std::string& label, const std::string& value) : label(label), value(value) {} @@ -48,67 +63,72 @@ namespace Swift { return options; } - const std::vector<std::string>& getRawValues() const { - return rawValues; + const std::vector<std::string>& getValues() const { + return values; } - void addRawValue(const std::string& value) { - rawValues.push_back(value); + void addValue(const std::string& value) { + values.push_back(value); } - protected: - FormField() : required(false) {} + Type getType() const { + return type; + } - private: - std::string name; - std::string label; - std::string description; - bool required; - std::vector<Option> options; - std::vector<std::string> rawValues; - }; + void setType(Type type) { + this->type = type; + } - template<typename T> class GenericFormField : public FormField { - public: - const T& getValue() const { - return value; + // Type specific + + bool getBoolValue() const { + assert(type == BooleanType || type == UnknownType); + if (values.empty()) { + return false; + } + return values[0] == "true" || values[0] == "1"; } - void setValue(const T& value) { - this->value = value; + void setBoolValue(bool b); + + JID getJIDSingleValue() const { + assert(type == JIDSingleType || type == UnknownType); + return values.empty() ? JID() : JID(values[0]); } + JID getJIDMultiValue(size_t index) const { + assert(type == JIDMultiType || type == UnknownType); + return values.empty() ? JID() : JID(values[index]); + } + + std::string getTextPrivateValue() const { + assert(type == TextPrivateType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getFixedValue() const { + assert(type == FixedType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getTextSingleValue() const { + assert(type == TextSingleType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getTextMultiValue() const; + void setTextMultiValue(const std::string& value); + protected: - GenericFormField() : value() {} - GenericFormField(const T& value) : value(value) {} private: - T value; - }; - -#define SWIFTEN_DECLARE_FORM_FIELD(name, valueType) \ - class name##FormField : public GenericFormField< valueType > { \ - public: \ - typedef boost::shared_ptr<name##FormField> ref; \ - static ref create(const valueType& value) { \ - return ref(new name##FormField(value)); \ - } \ - static ref create() { \ - return ref(new name##FormField()); \ - } \ - private: \ - name##FormField(valueType value) : GenericFormField< valueType >(value) {} \ - name##FormField() : GenericFormField< valueType >() {} \ + Type type; + std::string name; + std::string label; + std::string description; + bool required; + std::vector<Option> options; + std::vector<std::string> values; }; - SWIFTEN_DECLARE_FORM_FIELD(Boolean, bool) - SWIFTEN_DECLARE_FORM_FIELD(Fixed, std::string) - SWIFTEN_DECLARE_FORM_FIELD(Hidden, std::string) - SWIFTEN_DECLARE_FORM_FIELD(ListSingle, std::string) - SWIFTEN_DECLARE_FORM_FIELD(TextMulti, std::string) - SWIFTEN_DECLARE_FORM_FIELD(TextPrivate, std::string) - SWIFTEN_DECLARE_FORM_FIELD(TextSingle, std::string) - SWIFTEN_DECLARE_FORM_FIELD(JIDSingle, JID) - SWIFTEN_DECLARE_FORM_FIELD(JIDMulti, std::vector<JID>) - SWIFTEN_DECLARE_FORM_FIELD(ListMulti, std::vector<std::string>) } diff --git a/Swiften/Elements/UnitTest/FormTest.cpp b/Swiften/Elements/UnitTest/FormTest.cpp index 1134182..3000c22 100644 --- a/Swiften/Elements/UnitTest/FormTest.cpp +++ b/Swiften/Elements/UnitTest/FormTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Elements/Form.h> @@ -23,13 +24,13 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType() { Form form; - form.addField(FixedFormField::create("Foo")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); - FormField::ref field = HiddenFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); field->setName("FORM_TYPE"); form.addField(field); - form.addField(FixedFormField::create("Bar")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Bar")); CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), form.getFormType()); } @@ -37,7 +38,7 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType_InvalidFormType() { Form form; - FormField::ref field = FixedFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::FixedType, "jabber:bot"); field->setName("FORM_TYPE"); form.addField(field); @@ -47,7 +48,7 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType_NoFormType() { Form form; - form.addField(FixedFormField::create("Foo")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); } diff --git a/Swiften/Parser/PayloadParsers/FormParser.cpp b/Swiften/Parser/PayloadParsers/FormParser.cpp index 2df0a85..7c29189 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.cpp +++ b/Swiften/Parser/PayloadParsers/FormParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,7 +10,7 @@ namespace Swift { -FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false) { +FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false), parsingOption_(false) { } void FormParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { @@ -36,67 +36,62 @@ void FormParser::handleStartElement(const std::string& element, const std::strin else if (element == "instructions") { currentText_.clear(); } - else if (element == "field") { - std::string type; - FormField::ref correspondingReportedField; - if (!parsingItem_) { - type = attributes.getAttribute("type"); - } else { - foreach(FormField::ref field, getPayloadInternal()->getReportedFields()) { - if (field->getName() == attributes.getAttribute("var")) { - correspondingReportedField = field; - break; - } - } - } - if (type == "boolean" || boost::dynamic_pointer_cast<BooleanFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = BooleanFormFieldParseHelper::create(); - } - else if (type == "fixed" || boost::dynamic_pointer_cast<FixedFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = FixedFormFieldParseHelper::create(); + else if (element == "reported") { + parsingReported_ = true; + } + else if (element == "item") { + parsingItem_ = true; + } + } + else if (level_ == FieldLevel && currentField_) { + currentText_.clear(); + if (element == "option") { + currentOptionLabel_ = attributes.getAttribute("label"); + currentOptionValue_ = ""; + parsingOption_ = true; + } + } + if (level_ >= PayloadLevel) { + if (element == "field") { + currentField_ = boost::make_shared<FormField>(); + std::string type = attributes.getAttribute("type"); + FormField::Type fieldType = FormField::UnknownType; + if (type == "boolean") { + fieldType = FormField::BooleanType; } - else if (type == "hidden" || boost::dynamic_pointer_cast<HiddenFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = HiddenFormFieldParseHelper::create(); + if (type == "fixed") { + fieldType = FormField::FixedType; } - else if (type == "jid-multi" || boost::dynamic_pointer_cast<JIDMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = JIDMultiFormFieldParseHelper::create(); + if (type == "hidden") { + fieldType = FormField::HiddenType; } - else if (type == "jid-single" || boost::dynamic_pointer_cast<JIDSingleFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = JIDSingleFormFieldParseHelper::create(); + if (type == "list-single") { + fieldType = FormField::ListSingleType; } - else if (type == "list-multi" || boost::dynamic_pointer_cast<ListMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = ListMultiFormFieldParseHelper::create(); + if (type == "text-multi") { + fieldType = FormField::TextMultiType; } - else if (type == "list-single" || boost::dynamic_pointer_cast<ListSingleFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = ListSingleFormFieldParseHelper::create(); + if (type == "text-private") { + fieldType = FormField::TextPrivateType; } - else if (type == "text-multi" || boost::dynamic_pointer_cast<TextMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = TextMultiFormFieldParseHelper::create(); + if (type == "text-single") { + fieldType = FormField::TextSingleType; } - else if (type == "text-private" || boost::dynamic_pointer_cast<TextPrivateFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = TextPrivateFormFieldParseHelper::create(); + if (type == "jid-single") { + fieldType = FormField::JIDSingleType; } - else /*if (type == "text-single") || undefined */ { - currentFieldParseHelper_ = TextSingleFormFieldParseHelper::create(); + if (type == "jid-multi") { + fieldType = FormField::JIDMultiType; } - if (currentFieldParseHelper_) { - currentFieldParseHelper_->getField()->setName(attributes.getAttribute("var")); - currentFieldParseHelper_->getField()->setLabel(attributes.getAttribute("label")); + if (type == "list-multi") { + fieldType = FormField::ListMultiType; } + currentField_->setType(fieldType); + currentField_->setName(attributes.getAttribute("var")); + currentField_->setLabel(attributes.getAttribute("label")); } - else if (element == "reported") { - parsingReported_ = true; - level_ = PayloadLevel - 1; - } - else if (element == "item") { - parsingItem_ = true; - level_ = PayloadLevel - 1; - } - } - else if (level_ == FieldLevel && currentFieldParseHelper_) { - currentText_.clear(); - if (element == "option") { - currentOptionLabel_ = attributes.getAttribute("label"); + else if (element == "value") { + currentText_.clear(); } } ++level_; @@ -123,42 +118,48 @@ void FormParser::handleEndElement(const std::string& element, const std::string& getPayloadInternal()->setInstructions(currentInstructions + "\n" + currentText_); } } - else if (element == "field") { - if (currentFieldParseHelper_) { - if (parsingReported_) { - getPayloadInternal()->addReportedField(currentFieldParseHelper_->getField()); - } else if (parsingItem_) { - currentFields_.push_back(currentFieldParseHelper_->getField()); - } else { - getPayloadInternal()->addField(currentFieldParseHelper_->getField()); - } - currentFieldParseHelper_.reset(); - } + else if (element == "reported") { + parsingReported_ = false; + } + else if (element == "item") { + parsingItem_ = false; + getPayloadInternal()->addItem(currentFields_); + currentFields_.clear(); } } - else if (level_ == FieldLevel && currentFieldParseHelper_) { + else if (currentField_) { if (element == "required") { - currentFieldParseHelper_->getField()->setRequired(true); + currentField_->setRequired(true); } else if (element == "desc") { - currentFieldParseHelper_->getField()->setDescription(currentText_); + currentField_->setDescription(currentText_); } else if (element == "option") { - currentFieldParseHelper_->getField()->addOption(FormField::Option(currentOptionLabel_, currentText_)); + currentField_->addOption(FormField::Option(currentOptionLabel_, currentOptionValue_)); + parsingOption_ = false; } else if (element == "value") { - currentFieldParseHelper_->addValue(currentText_); + if (parsingOption_) { + currentOptionValue_ = currentText_; + } + else { + currentField_->addValue(currentText_); + } } } - if (element == "reported") { - parsingReported_ = false; - level_++; - } - else if (element == "item") { - parsingItem_ = false; - level_++; - getPayloadInternal()->addItem(currentFields_); - currentFields_.clear(); + if (level_ >= PayloadLevel && currentField_) { + if (element == "field") { + if (parsingReported_) { + getPayloadInternal()->addReportedField(currentField_); + } + else if (parsingItem_) { + currentFields_.push_back(currentField_); + } + else { + getPayloadInternal()->addField(currentField_); + } + currentField_.reset(); + } } } diff --git a/Swiften/Parser/PayloadParsers/FormParser.h b/Swiften/Parser/PayloadParsers/FormParser.h index ec480a5..0b23a81 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.h +++ b/Swiften/Parser/PayloadParsers/FormParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,86 +18,6 @@ namespace Swift { virtual void handleEndElement(const std::string& element, const std::string&); virtual void handleCharacterData(const std::string& data); - private: - class FieldParseHelper { - public: - virtual ~FieldParseHelper() {} - virtual void addValue(const std::string&) = 0; - virtual boost::shared_ptr<FormField> getField() const { - return field; - } - protected: - boost::shared_ptr<FormField> field; - }; - class BoolFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - boost::dynamic_pointer_cast< GenericFormField<bool> >(getField())->setValue(s == "1" || s == "true"); - getField()->addRawValue(s); - } - }; - class StringFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - boost::shared_ptr<GenericFormField<std::string> > field = boost::dynamic_pointer_cast< GenericFormField<std::string> >(getField()); - if (field->getValue().empty()) { - field->setValue(s); - } - else { - field->setValue(field->getValue() + "\n" + s); - } - getField()->addRawValue(s); - } - }; - class JIDFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - getField()->addRawValue(s); - boost::dynamic_pointer_cast< GenericFormField<JID> >(getField())->setValue(JID(s)); - } - }; - class StringListFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - // FIXME: Inefficient, but too much hassle to do efficiently - boost::shared_ptr<GenericFormField< std::vector<std::string> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<std::string > > >(getField()); - std::vector<std::string> l = field->getValue(); - l.push_back(s); - field->setValue(l); - getField()->addRawValue(s); - } - }; - class JIDListFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - // FIXME: Inefficient, but too much hassle to do efficiently - boost::shared_ptr< GenericFormField< std::vector<JID> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<JID > > >(getField()); - std::vector<JID> l = field->getValue(); - l.push_back(JID(s)); - field->setValue(l); - getField()->addRawValue(s); - } - }; - -#define SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(name, baseParser) \ - class name##FormFieldParseHelper : public baseParser##FieldParseHelper { \ - public: \ - typedef boost::shared_ptr<name##FormFieldParseHelper> ref; \ - static ref create() { \ - return ref(new name##FormFieldParseHelper()); \ - } \ - private: \ - name##FormFieldParseHelper() : baseParser##FieldParseHelper() { \ - field = name##FormField::create(); \ - } \ - } - - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Boolean, Bool); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Fixed, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Hidden, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListSingle, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextMulti, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextPrivate, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextSingle, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDSingle, JID); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDMulti, JIDList); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListMulti, StringList); - enum Level { TopLevel = 0, PayloadLevel = 1, @@ -106,9 +26,11 @@ namespace Swift { int level_; std::string currentText_; std::string currentOptionLabel_; - boost::shared_ptr<FieldParseHelper> currentFieldParseHelper_; + std::string currentOptionValue_; bool parsingItem_; bool parsingReported_; + bool parsingOption_; + FormField::ref currentField_; std::vector<FormField::ref> currentFields_; }; } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp index 20bad8c..ff0a061 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp @@ -96,8 +96,8 @@ void StreamInitiationParser::handleEndElement(const std::string& element, const } } else if (form->getType() == Form::SubmitType) { - if (field->getRawValues().size() > 0) { - getPayloadInternal()->setRequestedMethod(field->getRawValues()[0]); + if (!field->getValues().empty()) { + getPayloadInternal()->setRequestedMethod(field->getValues()[0]); } } } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp index c36fbeb..bc8f1bc 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -54,13 +54,13 @@ class FormParserTest : public CppUnit::TestFixture { "</field>" "<field label=\"Password for special access\" type=\"text-private\" var=\"password\"/>" "<field label=\"What features will the bot support?\" type=\"list-multi\" var=\"features\">" - "<value>news</value>" - "<value>search</value>" "<option label=\"Contests\"><value>contests</value></option>" "<option label=\"News\"><value>news</value></option>" "<option label=\"Polls\"><value>polls</value></option>" "<option label=\"Reminders\"><value>reminders</value></option>" "<option label=\"Search\"><value>search</value></option>" + "<value>news</value>" + "<value>search</value>" "</field>" "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" "<value>20</value>" @@ -84,37 +84,35 @@ class FormParserTest : public CppUnit::TestFixture { Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); CPPUNIT_ASSERT_EQUAL(10, static_cast<int>(payload->getFields().size())); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), boost::dynamic_pointer_cast<HiddenFormField>(payload->getFields()[0])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), payload->getFields()[0]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("FORM_TYPE"), payload->getFields()[0]->getName()); CPPUNIT_ASSERT(!payload->getFields()[0]->getRequired()); - CPPUNIT_ASSERT_EQUAL(std::string("Section 1: Bot Info"), boost::dynamic_pointer_cast<FixedFormField>(payload->getFields()[1])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("Section 1: Bot Info"), payload->getFields()[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("The name of your bot"), payload->getFields()[2]->getLabel()); - CPPUNIT_ASSERT_EQUAL(std::string("This is a bot.\nA quite good one actually"), boost::dynamic_pointer_cast<TextMultiFormField>(payload->getFields()[3])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("This is a bot.\nA quite good one actually"), payload->getFields()[3]->getTextMultiValue()); - CPPUNIT_ASSERT_EQUAL(true, boost::dynamic_pointer_cast<BooleanFormField>(payload->getFields()[4])->getValue()); + CPPUNIT_ASSERT_EQUAL(true, payload->getFields()[4]->getBoolValue()); CPPUNIT_ASSERT(payload->getFields()[4]->getRequired()); - CPPUNIT_ASSERT_EQUAL(std::string("1"), boost::dynamic_pointer_cast<BooleanFormField>(payload->getFields()[4])->getRawValues()[0]); - - CPPUNIT_ASSERT_EQUAL(std::string("news"), boost::dynamic_pointer_cast<ListMultiFormField>(payload->getFields()[6])->getValue()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getRawValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("search"), boost::dynamic_pointer_cast<ListMultiFormField>(payload->getFields()[6])->getValue()[1]); - CPPUNIT_ASSERT_EQUAL(std::string("search"), payload->getFields()[6]->getRawValues()[1]); + CPPUNIT_ASSERT_EQUAL(std::string("1"), payload->getFields()[4]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getFields()[6]->getValues().size())); + CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("search"), payload->getFields()[6]->getValues()[1]); CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(payload->getFields()[6]->getOptions().size())); CPPUNIT_ASSERT_EQUAL(std::string("Contests"), payload->getFields()[6]->getOptions()[0].label); CPPUNIT_ASSERT_EQUAL(std::string("contests"), payload->getFields()[6]->getOptions()[0].value); CPPUNIT_ASSERT_EQUAL(std::string("News"), payload->getFields()[6]->getOptions()[1].label); CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getOptions()[1].value); - CPPUNIT_ASSERT_EQUAL(std::string("20"), boost::dynamic_pointer_cast<ListSingleFormField>(payload->getFields()[7])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("20"), payload->getFields()[7]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), boost::dynamic_pointer_cast<JIDMultiFormField>(payload->getFields()[8])->getValue()[0]); - CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), boost::dynamic_pointer_cast<JIDMultiFormField>(payload->getFields()[8])->getValue()[1]); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), payload->getFields()[8]->getJIDMultiValue(0)); + CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), payload->getFields()[8]->getJIDMultiValue(1)); CPPUNIT_ASSERT_EQUAL(std::string("Tell all your friends about your new bot!"), payload->getFields()[8]->getDescription()); - CPPUNIT_ASSERT_EQUAL(std::string("foo"), boost::dynamic_pointer_cast<TextSingleFormField>(payload->getFields()[9])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->getFields()[9]->getValues()[0]); } void testParse_FormItems() { @@ -157,29 +155,28 @@ class FormParserTest : public CppUnit::TestFixture { Form::FormItem item = items[0]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - JIDSingleFormField::ref jidField = boost::dynamic_pointer_cast<JIDSingleFormField>(item[2]); - CPPUNIT_ASSERT(jidField); - CPPUNIT_ASSERT_EQUAL(JID("benvolio@montague.net"), jidField->getValue()); + boost::shared_ptr<FormField> jidField = item[2]; + CPPUNIT_ASSERT_EQUAL(JID("benvolio@montague.net"), jidField->getJIDSingleValue()); CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); item = items[1]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - jidField = boost::dynamic_pointer_cast<JIDSingleFormField>(item[2]); + jidField = item[2]; CPPUNIT_ASSERT(jidField); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), jidField->getValue()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), jidField->getJIDSingleValue()); CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp index ef48ced..59ea3ff 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -155,25 +155,25 @@ class SearchPayloadParserTest : public CppUnit::TestFixture { Form::FormItem item = items[0]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("benvolio@montague.net"), item[2]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("benvolio@montague.net"), item[2]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); item = items[1]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("romeo@montague.net"), item[2]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("romeo@montague.net"), item[2]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); } }; diff --git a/Swiften/SConscript b/Swiften/SConscript index b2c47f1..3edb463 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -120,6 +120,7 @@ if env["SCONS_STAGE"] == "build" : "Elements/DiscoInfo.cpp", "Elements/Presence.cpp", "Elements/Form.cpp", + "Elements/FormField.cpp", "Elements/StreamFeatures.cpp", "Elements/Element.cpp", "Elements/IQ.cpp", diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp index ba658e3..cf0f4ea 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -37,6 +37,10 @@ FormSerializer::FormSerializer() : GenericPayloadSerializer<Form>() { } std::string FormSerializer::serializePayload(boost::shared_ptr<Form> form) const { + if (!form) { + return ""; + } + boost::shared_ptr<XMLElement> formElement(new XMLElement("x", "jabber:x:data")); std::string type; switch (form->getType()) { @@ -92,66 +96,27 @@ boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormF // Set the value and type std::string fieldType; - if (boost::dynamic_pointer_cast<BooleanFormField>(field)) { - fieldType = "boolean"; - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast<BooleanFormField>(field)->getValue() ? "1" : "0")); - fieldElement->addNode(valueElement); - } - else if (boost::dynamic_pointer_cast<FixedFormField>(field)) { - fieldType = "fixed"; - serializeValueAsString<FixedFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<HiddenFormField>(field)) { - fieldType = "hidden"; - serializeValueAsString<HiddenFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<ListSingleFormField>(field)) { - fieldType = "list-single"; - serializeValueAsString<ListSingleFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<TextPrivateFormField>(field)) { - fieldType = "text-private"; - serializeValueAsString<TextPrivateFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<TextSingleFormField>(field)) { - fieldType = "text-single"; - serializeValueAsString<TextSingleFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<JIDMultiFormField>(field)) { - fieldType = "jid-multi"; - std::vector<JID> jids = boost::dynamic_pointer_cast<JIDMultiFormField>(field)->getValue(); - foreach(const JID& jid, jids) { - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(jid.toString())); - fieldElement->addNode(valueElement); - } - } - else if (boost::dynamic_pointer_cast<JIDSingleFormField>(field)) { - fieldType = "jid-single"; - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast<JIDSingleFormField>(field)->getValue().toString())); - if ( boost::dynamic_pointer_cast<JIDSingleFormField>(field)->getValue().isValid()) fieldElement->addNode(valueElement); - } - else if (boost::dynamic_pointer_cast<ListMultiFormField>(field)) { - fieldType = "list-multi"; - std::vector<std::string> lines = boost::dynamic_pointer_cast<ListMultiFormField>(field)->getValue(); - foreach(const std::string& line, lines) { - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(line)); - fieldElement->addNode(valueElement); - } - } - else if (boost::dynamic_pointer_cast<TextMultiFormField>(field)) { - fieldType = "text-multi"; - multiLineify(boost::dynamic_pointer_cast<TextMultiFormField>(field)->getValue(), "value", fieldElement); - } - else { - assert(false); + switch (field->getType()) { + case FormField::UnknownType: fieldType = ""; break; + case FormField::BooleanType: fieldType = "boolean"; break; + case FormField::FixedType: fieldType = "fixed"; break; + case FormField::HiddenType: fieldType = "hidden"; break; + case FormField::ListSingleType: fieldType = "list-single"; break; + case FormField::TextMultiType: fieldType = "text-multi"; break; + case FormField::TextPrivateType: fieldType = "text-private"; break; + case FormField::TextSingleType: fieldType = "text-single"; break; + case FormField::JIDSingleType: fieldType = "jid-single"; break; + case FormField::JIDMultiType: fieldType = "jid-multi"; break; + case FormField::ListMultiType: fieldType = "list-multi"; break; } if (!fieldType.empty() && withTypeAttribute) { fieldElement->setAttribute("type", fieldType); } + foreach (const std::string& value, field->getValues()) { + boost::shared_ptr<XMLElement> valueElement = boost::make_shared<XMLElement>("value"); + valueElement->addNode(boost::make_shared<XMLTextNode>(value)); + fieldElement->addNode(valueElement); + } foreach (const FormField::Option& option, field->getOptions()) { boost::shared_ptr<XMLElement> optionElement(new XMLElement("option")); diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.h b/Swiften/Serializer/PayloadSerializers/FormSerializer.h index bb31c97..f0f365c 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp index 030b024..973ced9 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -52,7 +52,7 @@ std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<Strea boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", FEATURE_NEG_NS)); if (streamInitiation->getProvidedMethods().size() > 0) { Form::ref form(new Form(Form::FormType)); - ListSingleFormField::ref field = ListSingleFormField::create(); + FormField::ref field = boost::make_shared<FormField>(FormField::ListSingleType); field->setName("stream-method"); foreach(const std::string& method, streamInitiation->getProvidedMethods()) { field->addOption(FormField::Option("", method)); @@ -62,7 +62,8 @@ std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<Strea } else if (!streamInitiation->getRequestedMethod().empty()) { Form::ref form(new Form(Form::SubmitType)); - ListSingleFormField::ref field = ListSingleFormField::create(streamInitiation->getRequestedMethod()); + FormField::ref field = boost::make_shared<FormField>(FormField::ListSingleType); + field->addValue(streamInitiation->getRequestedMethod()); field->setName("stream-method"); form->addField(field); featureElement->addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp index 4608522..e4ce2c8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 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 <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> using namespace Swift; @@ -36,37 +37,37 @@ class FormSerializerTest : public CppUnit::TestFixture { FormSerializer testling; boost::shared_ptr<Form> form(new Form(Form::FormType)); - FormField::ref field = HiddenFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); field->setName("FORM_TYPE"); form->addField(field); - form->addField(FixedFormField::create("Section 1: Bot Info")); + form->addField(boost::make_shared<FormField>(FormField::FixedType, "Section 1: Bot Info")); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("botname"); field->setLabel("The name of your bot"); form->addField(field); - field = TextMultiFormField::create("This is a bot.\nA quite good one actually"); + field = boost::make_shared<FormField>(FormField::TextMultiType); + field->setTextMultiValue("This is a bot.\nA quite good one actually"); field->setName("description"); field->setLabel("Helpful description of your bot"); form->addField(field); - field = BooleanFormField::create(true); + field = boost::make_shared<FormField>(FormField::BooleanType, "1"); field->setName("public"); field->setLabel("Public bot?"); field->setRequired(true); form->addField(field); - field = TextPrivateFormField::create(); + field = boost::make_shared<FormField>(FormField::TextPrivateType); field->setName("password"); field->setLabel("Password for special access"); form->addField(field); - std::vector<std::string> values; - values.push_back("news"); - values.push_back("search"); - field = ListMultiFormField::create(values); + field = boost::make_shared<FormField>(FormField::ListMultiType); + field->addValue("news"); + field->addValue("search"); field->setName("features"); field->setLabel("What features will the bot support?"); field->addOption(FormField::Option("Contests", "contests")); @@ -76,7 +77,7 @@ class FormSerializerTest : public CppUnit::TestFixture { field->addOption(FormField::Option("Search", "search")); form->addField(field); - field = ListSingleFormField::create("20"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "20"); field->setName("maxsubs"); field->setLabel("Maximum number of subscribers"); field->addOption(FormField::Option("10", "10")); @@ -88,9 +89,9 @@ class FormSerializerTest : public CppUnit::TestFixture { form->addField(field); std::vector<JID> jids; - jids.push_back(JID("foo@bar.com")); - jids.push_back(JID("baz@fum.org")); - field = JIDMultiFormField::create(jids); + field = boost::make_shared<FormField>(FormField::JIDMultiType); + field->addValue("foo@bar.com"); + field->addValue("baz@fum.org"); field->setName("invitelist"); field->setLabel("People to invite"); field->setDescription("Tell all your friends about your new bot!"); @@ -140,62 +141,62 @@ class FormSerializerTest : public CppUnit::TestFixture { boost::shared_ptr<Form> form(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("jabber:iq:search"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); field->setName("FORM_TYPE"); form->addField(field); // reported fields - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("first"); field->setLabel("Given Name"); form->addReportedField(field); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("last"); field->setLabel("Family Name"); form->addReportedField(field); - field = JIDSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::JIDSingleType); field->setName("jid"); field->setLabel("Jabber ID"); form->addReportedField(field); - field = ListSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::ListSingleType); field->setName("x-gender"); field->setLabel("Gender"); form->addReportedField(field); Form::FormItem firstItem; - field = TextSingleFormField::create("Benvolio"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); field->setName("first"); firstItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); firstItem.push_back(field); - field = JIDSingleFormField::create(JID("benvolio@montague.net")); + field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("benvolio@montague.net")); field->setName("jid"); firstItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); firstItem.push_back(field); Form::FormItem secondItem; - field = TextSingleFormField::create("Romeo"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); field->setName("first"); secondItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); secondItem.push_back(field); - field = JIDSingleFormField::create(JID("romeo@montague.net")); + field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("romeo@montague.net")); field->setName("jid"); secondItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); secondItem.push_back(field); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp index df43e69..7cbce35 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 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 <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> @@ -38,7 +39,7 @@ class InBandRegistrationPayloadSerializerTest : public CppUnit::TestFixture { boost::shared_ptr<Form> form(new Form(Form::FormType)); form->setTitle("Contest Registration"); - FormField::ref field = HiddenFormField::create("jabber:iq:register"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:register"); field->setName("FORM_TYPE"); form->addField(field); registration->setForm(form); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp index 42bff72..29e20c9 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 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 <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> @@ -78,62 +79,62 @@ class SearchPayloadSerializerTest : public CppUnit::TestFixture { SearchPayload::ref payload(new SearchPayload()); boost::shared_ptr<Form> form(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("jabber:iq:search"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); field->setName("FORM_TYPE"); form->addField(field); // reported fields - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("first"); field->setLabel("Given Name"); form->addReportedField(field); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("last"); field->setLabel("Family Name"); form->addReportedField(field); - field = JIDSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::JIDSingleType); field->setName("jid"); field->setLabel("Jabber ID"); form->addReportedField(field); - field = ListSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::ListSingleType); field->setName("x-gender"); field->setLabel("Gender"); form->addReportedField(field); Form::FormItem firstItem; - field = TextSingleFormField::create("Benvolio"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); field->setName("first"); firstItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); firstItem.push_back(field); - field = TextSingleFormField::create("benvolio@montague.net"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "benvolio@montague.net"); field->setName("jid"); firstItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); firstItem.push_back(field); Form::FormItem secondItem; - field = TextSingleFormField::create("Romeo"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); field->setName("first"); secondItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); secondItem.push_back(field); - field = TextSingleFormField::create("romeo@montague.net"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "romeo@montague.net"); field->setName("jid"); secondItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); secondItem.push_back(field); |