/* * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include #include #include #include #include #include #include #include #include #include using namespace Swift; namespace { template void serializeValueAsString(boost::shared_ptr field, boost::shared_ptr parent) { std::string value = boost::dynamic_pointer_cast(field)->getValue(); if (!value.empty()) { boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(value)); parent->addNode(valueElement); } } } namespace Swift { FormSerializer::FormSerializer() : GenericPayloadSerializer
() { } std::string FormSerializer::serializePayload(boost::shared_ptr form) const { if (!form) { return ""; } boost::shared_ptr formElement(new XMLElement("x", "jabber:x:data")); std::string type; switch (form->getType()) { case Form::FormType: type = "form"; break; case Form::SubmitType: type = "submit"; break; case Form::CancelType: type = "cancel"; break; case Form::ResultType: type = "result"; break; } formElement->setAttribute("type", type); if (!form->getTitle().empty()) { multiLineify(form->getTitle(), "title", formElement); } if (!form->getInstructions().empty()) { multiLineify(form->getInstructions(), "instructions", formElement); } foreach(boost::shared_ptr field, form->getFields()) { formElement->addNode(fieldToXML(field, true)); } if (!form->getReportedFields().empty()) { boost::shared_ptr reportedElement(new XMLElement("reported")); foreach(FormField::ref field, form->getReportedFields()) { reportedElement->addNode(fieldToXML(field, true)); } formElement->addNode(reportedElement); } foreach(Form::FormItem item, form->getItems()) { boost::shared_ptr itemElement(new XMLElement("item")); foreach(FormField::ref field, item) { itemElement->addNode(fieldToXML(field, false)); } formElement->addNode(itemElement); } return formElement->serialize(); } boost::shared_ptr FormSerializer::fieldToXML(boost::shared_ptr field, bool withTypeAttribute) const { boost::shared_ptr fieldElement(new XMLElement("field")); if (!field->getName().empty()) { fieldElement->setAttribute("var", field->getName()); } if (!field->getLabel().empty()) { fieldElement->setAttribute("label", field->getLabel()); } if (field->getRequired()) { fieldElement->addNode(boost::make_shared("required")); } if (!field->getDescription().empty()) { boost::shared_ptr descriptionElement(new XMLElement("desc")); descriptionElement->addNode(boost::make_shared(field->getDescription())); fieldElement->addNode(descriptionElement); } // Set the value and type std::string fieldType; 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 valueElement = boost::make_shared("value"); valueElement->addNode(boost::make_shared(value)); fieldElement->addNode(valueElement); } foreach (const FormField::Option& option, field->getOptions()) { boost::shared_ptr optionElement(new XMLElement("option")); if (!option.label.empty()) { optionElement->setAttribute("label", option.label); } boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(option.value)); optionElement->addNode(valueElement); fieldElement->addNode(optionElement); } return fieldElement; } void FormSerializer::multiLineify(const std::string& text, const std::string& elementName, boost::shared_ptr element) const { std::string unRdText(text); erase(unRdText, '\r'); std::vector lines = String::split(unRdText, '\n'); foreach (std::string line, lines) { boost::shared_ptr lineElement(new XMLElement(elementName)); lineElement->addNode(boost::make_shared(line)); element->addNode(lineElement); } } }