summaryrefslogtreecommitdiffstats
path: root/src/uscxml/messages
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/messages')
-rw-r--r--src/uscxml/messages/Blob.cpp61
-rw-r--r--src/uscxml/messages/Blob.h47
-rw-r--r--src/uscxml/messages/Data.cpp387
-rw-r--r--src/uscxml/messages/Data.h243
-rw-r--r--src/uscxml/messages/Event.cpp187
-rw-r--r--src/uscxml/messages/Event.h235
-rw-r--r--src/uscxml/messages/InvokeRequest.cpp91
-rw-r--r--src/uscxml/messages/InvokeRequest.h72
-rw-r--r--src/uscxml/messages/SendRequest.cpp135
-rw-r--r--src/uscxml/messages/SendRequest.h72
10 files changed, 1530 insertions, 0 deletions
diff --git a/src/uscxml/messages/Blob.cpp b/src/uscxml/messages/Blob.cpp
new file mode 100644
index 0000000..1d07e6a
--- /dev/null
+++ b/src/uscxml/messages/Blob.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/messages/Blob.h"
+
+#include "uscxml/util/MD5.hpp"
+#include "uscxml/util/Base64.hpp"
+
+namespace uscxml {
+
+Blob::~Blob() {
+ free(data);
+}
+
+std::string Blob::md5() {
+ return uscxml::md5(data, size);
+}
+
+Blob* Blob::fromBase64(const std::string base64) {
+ std::string decoded = base64Decode(base64);
+ return new Blob((void*)decoded.c_str(), decoded.length(), mimeType);
+}
+
+Blob::Blob(size_t _size) {
+ data = (char*)malloc(_size);
+ memset(data, 0, _size);
+ size = _size;
+}
+
+Blob::Blob(void* _data, size_t _size, const std::string& _mimeType, bool adopt) {
+ if (adopt) {
+ data = (char*)_data;
+ } else {
+ data = (char*)malloc(_size);
+ memcpy(data, _data, _size);
+ }
+ mimeType = _mimeType;
+ size = _size;
+}
+
+std::string Blob::base64() {
+ return base64Encode((char* const)data, size);
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/messages/Blob.h b/src/uscxml/messages/Blob.h
new file mode 100644
index 0000000..b4fcd46
--- /dev/null
+++ b/src/uscxml/messages/Blob.h
@@ -0,0 +1,47 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef BLOB_H_E1B6D2C3
+#define BLOB_H_E1B6D2C3
+
+#include <string>
+
+#include "uscxml/Common.h"
+
+namespace uscxml {
+
+class USCXML_API Blob {
+public:
+ ~Blob();
+ Blob(size_t size);
+ Blob(void* data, size_t size, const std::string& mimeType, bool adopt = false);
+ char* data;
+ size_t size;
+ std::string mimeType;
+
+ std::string base64();
+
+ std::string md5();
+ Blob* fromBase64(const std::string base64);
+
+};
+
+}
+
+#endif /* end of include guard: BLOB_H_E1B6D2C3 */
diff --git a/src/uscxml/messages/Data.cpp b/src/uscxml/messages/Data.cpp
new file mode 100644
index 0000000..6706253
--- /dev/null
+++ b/src/uscxml/messages/Data.cpp
@@ -0,0 +1,387 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/messages/Data.h"
+#include "uscxml/messages/Blob.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "uscxml/DOMUtils.h"
+#include "glog/logging.h"
+
+#ifdef HAS_STRING_H
+#include <string.h>
+#endif
+
+extern "C" {
+#include "jsmn.h" // minimal json parser
+}
+
+namespace uscxml {
+
+Data::Data(const char* _data, size_t _size, const std::string& mimeType, bool adopt) {
+ binary = boost::shared_ptr<Blob>(new Blob((void*)_data, _size, mimeType, adopt));
+}
+
+void Data::merge(const Data& other) {
+ if (other.compound.size() > 0) {
+ if (compound.size() == 0) {
+ compound = other.compound;
+ } else {
+ std::map<std::string, Data>::const_iterator compIter = other.compound.begin();
+ while (compIter != other.compound.end()) {
+ if (compound.find(compIter->first) != compound.end()) {
+ // we do have the same key, merge
+ compound[compIter->first].merge(compIter->second);
+ } else {
+ compound[compIter->first] = compIter->second;
+ }
+ compIter++;
+ }
+ }
+ }
+ if (other.array.size() > 0) {
+ if (array.size() == 0) {
+ array = other.array;
+ } else {
+ std::list<Data>::const_iterator arrIter = other.array.begin();
+ while(arrIter != other.array.end()) {
+ array.push_back(*arrIter);
+ arrIter++;
+ }
+ }
+ }
+ if (other.atom.size() > 0) {
+ atom = other.atom;
+ type = other.type;
+ }
+}
+
+Data::Data(const Arabica::DOM::Node<std::string>& dom) {
+ // we may need to convert some keys to arrays if we have the same name as an element
+ std::map<std::string, std::list<Data> > arrays;
+// Interpreter::dump(dom);
+
+ if (dom.hasAttributes()) {
+ Arabica::DOM::NamedNodeMap<std::string> attributes = dom.getAttributes();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Arabica::DOM::Node<std::string> attribute = attributes.item(i);
+// Interpreter::dump(attribute);
+
+ assert(attribute.getNodeType() == Arabica::DOM::Node_base::ATTRIBUTE_NODE);
+ std::string key = attribute.getLocalName();
+ std::string value = attribute.getNodeValue();
+ compound[key] = Data(value, VERBATIM);
+ }
+ }
+
+ if (dom.hasChildNodes()) {
+ Arabica::DOM::NodeList<std::string> children = dom.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Arabica::DOM::Node<std::string> child = children.item(i);
+// Interpreter::dump(child);
+ std::string key;
+ switch (child.getNodeType()) {
+ case Arabica::DOM::Node_base::ELEMENT_NODE:
+ key = TAGNAME(child);
+ break;
+ case Arabica::DOM::Node_base::ATTRIBUTE_NODE:
+ key = ((Arabica::DOM::Attr<std::string>)child).getName();
+ break;
+ case Arabica::DOM::Node_base::TEXT_NODE:
+ default:
+ break;
+ }
+ if (key.length() == 0)
+ continue;
+
+ if (compound.find(key) != compound.end()) {
+ // we already have such a key .. make it an array after we processed all children
+ arrays[key].push_back(Data(child));
+ } else {
+ compound[key] = Data(child);
+ }
+ }
+ } else {
+ atom = dom.getNodeValue();
+ type = VERBATIM;
+ }
+
+ std::map<std::string, std::list<Data> >::iterator arrayIter = arrays.begin();
+ while(arrayIter != arrays.end()) {
+ assert(compound.find(arrayIter->first) != compound.end());
+ Data arrayData;
+ arrays[arrayIter->first].push_front(compound[arrayIter->first]);
+ arrayData.array = arrays[arrayIter->first];
+ compound[arrayIter->first] = arrayData;
+ }
+}
+
+Arabica::DOM::Document<std::string> Data::toDocument() {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> document = domFactory.createDocument("http://www.w3.org/2005/07/scxml", "message", 0);
+ Arabica::DOM::Element<std::string> scxmlMsg = document.getDocumentElement();
+ scxmlMsg.setPrefix("scxml");
+ scxmlMsg.setAttribute("version", "1.0");
+
+ if (compound.size() > 0 || array.size() > 0) {
+ Arabica::DOM::Element<std::string> payloadElem = document.createElementNS("http://www.w3.org/2005/07/scxml", "payload");
+ payloadElem.setPrefix("scxml");
+
+ scxmlMsg.appendChild(payloadElem);
+
+ // we do not support nested attibutes
+ if (compound.size() > 0) {
+ std::map<std::string, Data>::iterator compoundIter = compound.begin();
+ while(compoundIter != compound.end()) {
+ if (compoundIter->second.atom.size() > 0) {
+ Arabica::DOM::Element<std::string> propertyElem = document.createElementNS("http://www.w3.org/2005/07/scxml", "property");
+ propertyElem.setPrefix("scxml");
+
+ propertyElem.setAttribute("name", compoundIter->first);
+ Arabica::DOM::Text<std::string> textElem = document.createTextNode(compoundIter->second.atom);
+ propertyElem.appendChild(textElem);
+ payloadElem.appendChild(propertyElem);
+ }
+ compoundIter++;
+ }
+ }
+ }
+ return document;
+}
+
+Data Data::fromXML(const std::string& xmlString) {
+ return Data();
+}
+
+Data Data::fromJSON(const std::string& jsonString) {
+ Data data;
+
+ std::string trimmed = boost::trim_copy(jsonString);
+
+ if (trimmed.length() == 0)
+ return data;
+
+ if (trimmed.find_first_of("{[") != 0)
+ return data;
+
+ jsmn_parser p;
+
+ jsmntok_t* t = NULL;
+
+ // we do not know the number of tokens beforehand, start with something sensible and increase
+ int rv;
+ int frac = 16; // length/token ratio
+ do {
+ jsmn_init(&p);
+
+ frac /= 2;
+ int nrTokens = trimmed.size() / frac;
+ if (t != NULL) {
+ free(t);
+// LOG(INFO) << "Increasing JSON length to token ratio to 1/" << frac;
+ }
+ t = (jsmntok_t*)malloc((nrTokens + 1) * sizeof(jsmntok_t));
+ if (t == NULL) {
+ LOG(ERROR) << "Cannot parse JSON, ran out of memory!";
+ return data;
+ }
+ memset(t, 0, (nrTokens + 1) * sizeof(jsmntok_t));
+
+ rv = jsmn_parse(&p, trimmed.c_str(), t, nrTokens);
+ } while (rv == JSMN_ERROR_NOMEM && frac > 1);
+
+ if (rv != 0) {
+ switch (rv) {
+ case JSMN_ERROR_NOMEM:
+ LOG(ERROR) << "Cannot parse JSON, not enough tokens were provided!";
+ break;
+ case JSMN_ERROR_INVAL:
+ LOG(ERROR) << "Cannot parse JSON, invalid character inside JSON string!";
+ break;
+ case JSMN_ERROR_PART:
+ LOG(ERROR) << "Cannot parse JSON, the string is not a full JSON packet, more bytes expected!";
+ break;
+ default:
+ break;
+ }
+ free(t);
+ return data;
+ }
+
+ if (t[0].end != trimmed.length())
+ return data;
+
+// jsmntok_t* token = t;
+// while(token->end) {
+// std::cout << trimmed.substr(token->start, token->end - token->start) << std::endl;
+// std::cout << "------" << std::endl;
+// token++;
+// }
+
+ std::list<Data*> dataStack;
+ std::list<jsmntok_t> tokenStack;
+ dataStack.push_back(&data);
+
+ size_t currTok = 0;
+ do {
+ // used for debugging
+// jsmntok_t t2 = t[currTok];
+// std::string value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start);
+ switch (t[currTok].type) {
+ case JSMN_STRING:
+ dataStack.back()->type = Data::VERBATIM;
+ case JSMN_PRIMITIVE: {
+ std::string value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start);
+ if (dataStack.back()->type == Data::VERBATIM) {
+ boost::replace_all(value, "\\\"", "\"");
+ boost::replace_all(value, "\\n", "\n");
+ }
+ dataStack.back()->atom = value;
+ dataStack.pop_back();
+ currTok++;
+ break;
+ }
+ case JSMN_OBJECT:
+ case JSMN_ARRAY:
+ tokenStack.push_back(t[currTok]);
+ currTok++;
+ break;
+ }
+ // used for debugging
+// t2 = t[currTok];
+// value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start);
+
+ // there are no more tokens
+ if (t[currTok].end == 0 || tokenStack.empty())
+ break;
+
+ // next token starts after current one => pop
+ while (t[currTok].end > tokenStack.back().end) {
+ tokenStack.pop_back();
+ dataStack.pop_back();
+ }
+
+ if (tokenStack.back().type == JSMN_OBJECT && (t[currTok].type == JSMN_PRIMITIVE || t[currTok].type == JSMN_STRING)) {
+ // grab key and push new data
+ std::string value = trimmed.substr(t[currTok].start, t[currTok].end - t[currTok].start);
+ dataStack.push_back(&(dataStack.back()->compound[value]));
+ currTok++;
+ }
+ if (tokenStack.back().type == JSMN_ARRAY) {
+ // push new index
+ dataStack.back()->array.push_back(Data());
+ dataStack.push_back(&(dataStack.back()->array.back()));
+ }
+
+ } while (true);
+
+ free(t);
+ return data;
+}
+
+std::ostream& operator<< (std::ostream& os, const Data& data) {
+ os << Data::toJSON(data);
+ return os;
+}
+
+std::string Data::toJSON(const Data& data) {
+ std::stringstream os;
+ std::string indent;
+ for (int i = 0; i < _dataIndentation; i++) {
+ indent += " ";
+ }
+ if (false) {
+ } else if (data.compound.size() > 0) {
+ int longestKey = 0;
+ std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
+ while(compoundIter != data.compound.end()) {
+ if (compoundIter->first.size() > longestKey)
+ longestKey = compoundIter->first.size();
+ compoundIter++;
+ }
+ std::string keyPadding;
+ for (unsigned int i = 0; i < longestKey; i++)
+ keyPadding += " ";
+
+ std::string seperator;
+ os << std::endl << indent << "{";
+ compoundIter = data.compound.begin();
+ while(compoundIter != data.compound.end()) {
+ os << seperator << std::endl << indent << " \"" << compoundIter->first << "\": " << keyPadding.substr(0, longestKey - compoundIter->first.size());
+ _dataIndentation += 1;
+ os << compoundIter->second;
+ _dataIndentation -= 1;
+ seperator = ", ";
+ compoundIter++;
+ }
+ os << std::endl << indent << "}";
+ } else if (data.array.size() > 0) {
+
+ std::string seperator;
+ os << std::endl << indent << "[";
+ std::list<Data>::const_iterator arrayIter = data.array.begin();
+ while(arrayIter != data.array.end()) {
+ _dataIndentation += 1;
+ os << seperator << *arrayIter;
+ _dataIndentation -= 1;
+ seperator = ", ";
+ arrayIter++;
+ }
+ os << "]";
+ } else if (data.atom.size() > 0) {
+ // empty string is handled below
+ if (data.type == Data::VERBATIM) {
+ os << "\"";
+ for (int i = 0; i < data.atom.size(); i++) {
+ // escape string
+ if (false) {
+ } else if (data.atom[i] == '"') {
+ os << "\\\"";
+ } else if (data.atom[i] == '\n') {
+ os << "\\n";
+ } else if (data.atom[i] == '\t') {
+ os << "\\t";
+ } else {
+ os << data.atom[i];
+ }
+ }
+ os << "\"";
+ } else {
+ os << data.atom;
+ }
+ } else if (data.node) {
+ std::ostringstream xmlSerSS;
+ xmlSerSS << data.node;
+ std::string xmlSer = xmlSerSS.str();
+ boost::replace_all(xmlSer, "\"", "\\\"");
+ boost::replace_all(xmlSer, "\n", "\\n");
+ boost::replace_all(xmlSer, "\t", "\\t");
+ os << "\"" << xmlSer << "\"";
+ } else {
+ if (data.type == Data::VERBATIM) {
+ os << "\"\""; // empty string
+ } else {
+ os << "null";
+ }
+ }
+ return os.str();
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h
new file mode 100644
index 0000000..bf13409
--- /dev/null
+++ b/src/uscxml/messages/Data.h
@@ -0,0 +1,243 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef DATA_H_09E4D8E5
+#define DATA_H_09E4D8E5
+
+#include <list>
+#include <map>
+
+#include <boost/shared_ptr.hpp>
+
+#include "uscxml/Common.h"
+#include "uscxml/Convenience.h"
+#include <DOM/Document.hpp>
+
+namespace uscxml {
+
+class Blob;
+
+static int _dataIndentation = 1;
+
+class USCXML_API Data {
+public:
+ enum Type {
+ VERBATIM,
+ INTERPRETED,
+ };
+
+ Data() : type(INTERPRETED) {}
+
+ // TODO: default INTERPRETED is unfortunate
+ Data(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {}
+ Data(const char* data, size_t size, const std::string& mimeType, bool adopt = false);
+
+ // convenience constructors
+ Data(short atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(int atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(unsigned int atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(long atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(unsigned long atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(float atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(double atom_) : atom(toStr(atom_)), type(INTERPRETED) {}
+ Data(bool atom_) : type(INTERPRETED) {
+ if (atom_) {
+ atom = "true";
+ } else {
+ atom = "false";
+ }
+ }
+
+ template <typename T> Data(T value, Type type_) : atom(toStr(value)), type(type_) {}
+
+#if 0
+ // constructor for arbitrary types, skip if type is subclass though (C++11)
+ // we will have to drop this constructor as it interferes with operator Data() and entails C++11
+ template <typename T>
+ Data(T value, typename std::enable_if<! std::is_base_of<Data, T>::value>::type* = nullptr)
+ : atom(toStr(value)), type(INTERPRETED) {}
+#endif
+
+
+ explicit Data(const Arabica::DOM::Node<std::string>& dom);
+ virtual ~Data() {}
+
+ bool empty() const {
+ bool hasContent = (atom.length() > 0 || !compound.empty() || !array.empty() || binary || node);
+ return !hasContent;
+ }
+
+ bool operator<(const Data& other) const {
+ std::string thisJSON = Data::toJSON(*this);
+ std::string otherJSON = Data::toJSON(other);
+ return (thisJSON < otherJSON);
+ }
+
+ void merge(const Data& other);
+
+ bool hasKey(const std::string& key) const {
+ return (!compound.empty() && compound.find(key) != compound.end());
+ }
+
+ Data& operator[](const std::string& key) {
+ return operator[](key.c_str());
+ }
+
+ const Data& operator[](const std::string& key) const {
+ return operator[](key.c_str());
+ }
+
+ Data& operator[](const char* key) {
+ return compound[key];
+ }
+
+ const Data& operator[](const char* key) const {
+ return compound.at(key);
+ }
+
+ Data& operator[](const size_t index) {
+ while(array.size() < index) {
+ array.push_back(Data("", Data::VERBATIM));
+ }
+ std::list<Data>::iterator arrayIter = array.begin();
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+
+ const Data at(const std::string& key) const {
+ return at(key.c_str());
+ }
+
+ const Data at(const char* key) const {
+ if (hasKey(key))
+ return compound.at(key);
+ Data data;
+ return data;
+ }
+
+ const Data item(const size_t index) const {
+ if (array.size() < index) {
+ std::list<Data>::const_iterator arrayIter;
+ for (int i = 0; i < index; i++, arrayIter++) {}
+ return *arrayIter;
+ }
+ Data data;
+ return data;
+ }
+
+ bool operator==(const Data &other) const {
+ if (other.atom.size() != atom.size())
+ return false;
+ if (other.type != type)
+ return false;
+ if (other.binary != binary)
+ return false;
+ if (other.array.size() != array.size())
+ return false;
+ if (other.compound.size() != compound.size())
+ return false;
+
+ if (other.atom != atom)
+ return false;
+ if (other.array != array)
+ return false;
+ if (other.compound != compound)
+ return false;
+ if (other.node != node)
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const Data &other) const {
+ return !(*this == other);
+ }
+
+ operator std::string() const {
+ return atom;
+ }
+
+ operator std::map<std::string, Data>() {
+ return compound;
+ }
+
+ operator std::list<Data>() {
+ return array;
+ }
+
+ static Data fromJSON(const std::string& jsonString);
+ static std::string toJSON(const Data& data);
+ static Data fromXML(const std::string& xmlString);
+ Arabica::DOM::Document<std::string> toDocument();
+ std::string toXMLString() {
+ std::stringstream ss;
+ ss << toDocument();
+ return ss.str();
+ }
+
+ std::map<std::string, Data> getCompound() {
+ return compound;
+ }
+ void setCompound(const std::map<std::string, Data>& compound) {
+ this->compound = compound;
+ }
+
+ std::list<Data> getArray() {
+ return array;
+ }
+ void setArray(const std::list<Data>& array) {
+ this->array = array;
+ }
+
+ std::string getAtom() {
+ return atom;
+ }
+ void setAtom(const std::string& atom) {
+ this->atom = atom;
+ }
+
+ Type getType() {
+ return type;
+ }
+ void setType(const Type type) {
+ this->type = type;
+ }
+
+
+#ifdef SWIGIMPORTED
+protected:
+#endif
+
+ Arabica::DOM::Node<std::string> node;
+ std::map<std::string, Data> compound;
+ std::list<Data> array;
+ std::string atom;
+ boost::shared_ptr<Blob> binary;
+ Type type;
+
+protected:
+ Arabica::DOM::Document<std::string> toNode(const Arabica::DOM::Document<std::string>& factory, const Data& data);
+ friend USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data);
+};
+
+USCXML_API std::ostream& operator<< (std::ostream& os, const Data& data);
+
+}
+
+#endif /* end of include guard: DATA_H_09E4D8E5 */
diff --git a/src/uscxml/messages/Event.cpp b/src/uscxml/messages/Event.cpp
new file mode 100644
index 0000000..a3e6a20
--- /dev/null
+++ b/src/uscxml/messages/Event.cpp
@@ -0,0 +1,187 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/messages/Event.h"
+#include "uscxml/DOMUtils.h"
+
+namespace uscxml {
+
+//Arabica::DOM::Node<std::string> Event::getFirstDOMElement() const {
+// return getFirstDOMElement(dom);
+//}
+//
+//Arabica::DOM::Document<std::string> Event::getStrippedDOM() const {
+// return getStrippedDOM(dom);
+//}
+
+//Arabica::DOM::Node<std::string> Event::getFirstDOMElement(const Arabica::DOM::Document<std::string> dom) {
+// Arabica::DOM::Node<std::string> data = dom.getDocumentElement().getFirstChild();
+// while (data) {
+// if (data.getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) {
+// std::string trimmed = boost::trim_copy(data.getNodeValue());
+// if (trimmed.length() == 0) {
+// data = data.getNextSibling();
+// continue;
+// }
+// }
+// break;
+// }
+// return data;
+//}
+//
+//Arabica::DOM::Document<std::string> Event::getStrippedDOM(const Arabica::DOM::Document<std::string> dom) {
+// Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+// Arabica::DOM::Document<std::string> document = domFactory.createDocument("", "", 0);
+// if (dom) {
+// document.getDocumentElement().appendChild(document.importNode(getFirstDOMElement(dom), true));
+// }
+// return document;
+//}
+
+std::string Event::toXMLString() {
+ std::stringstream ss;
+ ss << toDocument();
+ return ss.str();
+}
+
+Arabica::DOM::Document<std::string> Event::toDocument() {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> document = data.toDocument();
+ Arabica::DOM::Element<std::string> scxmlMsg = document.getDocumentElement();
+
+
+ scxmlMsg.setAttribute("source", origin);
+ scxmlMsg.setAttribute("name", name);
+
+ return document;
+}
+
+void Event::initContent(const std::string& content) {
+ // try to parse as JSON
+ Data json = Data::fromJSON(content);
+ if (!json.empty()) {
+ data = json;
+ return;
+ }
+
+ // try to parse as XML
+ Arabica::SAX2DOM::Parser<std::string> parser;
+ Arabica::SAX::CatchErrorHandler<std::string> errorHandler;
+ parser.setErrorHandler(errorHandler);
+
+ std::istringstream is(content);
+ Arabica::SAX::InputSource<std::string> inputSource;
+ inputSource.setByteStream(is);
+ if (parser.parse(inputSource)) {
+ dom = parser.getDocument();
+ return;
+ }
+
+ this->content = content;
+}
+
+Event Event::fromXML(const std::string& xmlString) {
+ Arabica::SAX2DOM::Parser<std::string> eventParser;
+ Arabica::SAX::CatchErrorHandler<std::string> errorHandler;
+ eventParser.setErrorHandler(errorHandler);
+
+ std::istringstream is(xmlString);
+ Arabica::SAX::InputSource<std::string> inputSource;
+ inputSource.setByteStream(is);
+
+ Event event;
+ if(eventParser.parse(inputSource) && eventParser.getDocument().hasChildNodes()) {
+ Arabica::DOM::Element<std::string> scxmlMsg = eventParser.getDocument().getDocumentElement();
+ if (HAS_ATTR(scxmlMsg, "name"))
+ event.name = ATTR(scxmlMsg, "name");
+ if (HAS_ATTR(scxmlMsg, "sendid"))
+ event.sendid = ATTR(scxmlMsg, "sendid");
+
+ Arabica::DOM::NodeList<std::string> payloads = scxmlMsg.getElementsByTagName("scxml:payload");
+ if (payloads.getLength() > 0) {
+ Arabica::DOM::Node<std::string> payload = payloads.item(0);
+ if (payload.getNodeType() == Arabica::DOM::Node_base::ELEMENT_NODE) {
+ Arabica::DOM::Element<std::string> payloadElem = (Arabica::DOM::Element<std::string>)payload;
+ Arabica::DOM::NodeList<std::string> properties = payloadElem.getElementsByTagName("scxml:property");
+ if (properties.getLength() > 0) {
+ for (int i = 0; i < properties.getLength(); i++) {
+ if (HAS_ATTR(properties.item(i), "name")) {
+ std::string key = ATTR(properties.item(i), "name");
+ std::string value;
+ Arabica::DOM::NodeList<std::string> childs = properties.item(i).getChildNodes();
+ for (int j = 0; j < childs.getLength(); j++) {
+ if (childs.item(j).getNodeType() == Arabica::DOM::Node_base::TEXT_NODE) {
+ value = childs.item(j).getNodeValue();
+ break;
+ }
+ }
+ event.data.compound[key] = Data(value, Data::VERBATIM);
+ }
+ }
+ }
+ }
+ }
+ }
+ return event;
+}
+
+std::ostream& operator<< (std::ostream& os, const Event& event) {
+ std::string indent;
+ for (int i = 0; i < _dataIndentation; i++) {
+ indent += " ";
+ }
+
+ os << indent << (event.eventType == Event::EXTERNAL ? "External" : "Internal") << " Event " << (event.dom ? "with DOM attached" : "") << std::endl;
+
+ if (event.name.size() > 0)
+ os << indent << " name: " << event.name << std::endl;
+ if (event.origin.size() > 0)
+ os << indent << " origin: " << event.origin << std::endl;
+ if (event.origintype.size() > 0)
+ os << indent << " origintype: " << event.origintype << std::endl;
+ if (event.params.size() > 0) {
+ std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin();
+ os << indent << " params:" << std::endl;
+ _dataIndentation++;
+ while(paramIter != event.params.end()) {
+ os << indent << " " << paramIter->first << ": ";
+ os << indent << paramIter->second << std::endl;
+ paramIter++;
+ }
+ _dataIndentation--;
+ }
+ if (event.namelist.size() > 0) {
+ std::map<std::string, Data>::const_iterator namelistIter = event.namelist.begin();
+ os << indent << " namelist:" << std::endl;
+ _dataIndentation++;
+ while(namelistIter != event.namelist.end()) {
+ os << indent << " " << namelistIter->first << ": ";
+ os << indent << namelistIter->second << std::endl;
+ namelistIter++;
+ }
+ _dataIndentation--;
+
+ }
+ _dataIndentation++;
+ os << indent << " data: " << event.data << std::endl;
+ _dataIndentation--;
+ return os;
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/messages/Event.h b/src/uscxml/messages/Event.h
new file mode 100644
index 0000000..1acfce7
--- /dev/null
+++ b/src/uscxml/messages/Event.h
@@ -0,0 +1,235 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef EVENT_H_6174D929
+#define EVENT_H_6174D929
+
+#include "uscxml/messages/Data.h"
+
+namespace uscxml {
+
+class USCXML_API Event {
+public:
+ enum Type {
+ INTERNAL = 1,
+ EXTERNAL = 2,
+ PLATFORM = 3
+ };
+
+ Event() : eventType(INTERNAL), hideSendId(false) {}
+ Event(const std::string& name, Type type = INTERNAL) : name(name), eventType(type), hideSendId(false) {}
+ Event(const Arabica::DOM::Node<std::string>& xmlString) : eventType(INTERNAL), hideSendId(false) {};
+ bool operator< (const Event& other) const {
+ return this < &other;
+ }
+
+ bool operator==(const Event& other) const {
+ return (this->name == other.name &&
+ this->sendid == other.sendid &&
+ this->invokeid == other.invokeid &&
+ this->data == other.data);
+ }
+ bool operator!=(const Event& other) const {
+ return !(*this == other);
+ }
+
+ std::string getName() {
+ return name;
+ }
+ void setName(const std::string& name) {
+ this->name = name;
+ }
+
+ Type getEventType() {
+ return eventType;
+ }
+ void setEventType(const Type type) {
+ this->eventType = type;
+ }
+
+ std::string getOrigin() {
+ return origin;
+ }
+ void setOrigin(const std::string& origin) {
+ this->origin = origin;
+ }
+
+ std::string getOriginType() {
+ return origintype;
+ }
+ void setOriginType(const std::string& originType) {
+ this->origintype = originType;
+ }
+
+ Arabica::DOM::Node<std::string> getDOM() {
+ return dom;
+ }
+ void setDOM(const Arabica::DOM::Node<std::string>& dom) {
+ this->dom = dom;
+ }
+
+// Arabica::DOM::Node<std::string> getFirstDOMElement() const;
+// Arabica::DOM::Document<std::string> getStrippedDOM() const;
+//
+// static Arabica::DOM::Node<std::string> getFirstDOMElement(const Arabica::DOM::Document<std::string> dom);
+// static Arabica::DOM::Document<std::string> getStrippedDOM(const Arabica::DOM::Document<std::string> dom);
+
+ std::string getRaw() {
+ return raw;
+ }
+ void setRaw(const std::string& raw) {
+ this->raw = raw;
+ }
+
+ std::string getContent() {
+ return content;
+ }
+ void setContent(const std::string& content) {
+ this->content = content;
+ }
+
+ std::string getXML() {
+ return xml;
+ }
+ void setXML(const std::string& xml) {
+ this->xml = xml;
+ }
+
+ std::string getSendId() {
+ return sendid;
+ }
+ void setSendId(const std::string& sendId) {
+ this->sendid = sendId;
+ }
+
+ std::string getInvokeId() {
+ return invokeid;
+ }
+ void setInvokeId(const std::string& invokeId) {
+ this->invokeid = invokeId;
+ }
+
+ Data getData() {
+ return data;
+ }
+ void setData(const Data& data) {
+ this->data = data;
+ }
+
+ void initContent(const std::string& content);
+
+ static Event fromXML(const std::string& xmlString);
+ Arabica::DOM::Document<std::string> toDocument();
+ std::string toXMLString();
+
+ std::map<std::string, Data>& getNameList() {
+ return namelist;
+ }
+ std::multimap<std::string, Data>& getParams() {
+ return params;
+ }
+
+ typedef std::multimap<std::string, Data> params_t;
+ typedef std::map<std::string, Data> namelist_t;
+
+ static bool getParam(params_t params, const std::string& name, Data& target) {
+ if (params.find(name) != params.end()) {
+ target = params.find(name)->second;
+ return true;
+ }
+ return false;
+ }
+
+ static bool getParam(params_t params, const std::string& name, std::list<Data>& target) {
+ if (params.find(name) != params.end()) {
+ std::pair<params_t::iterator, params_t::iterator> rangeIter = params.equal_range(name);
+ while(rangeIter.first != rangeIter.second) {
+ target.push_back(rangeIter.first->second);
+ rangeIter.first++;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T> static bool getParam(params_t params, const std::string& name, T& target) {
+ if (params.find(name) != params.end()) {
+ target = boost::lexical_cast<T>(params.find(name)->second.atom);
+ return true;
+ }
+ return false;
+ }
+
+ static bool getParam(params_t params, const std::string& name, bool& target) {
+ if (params.find(name) != params.end()) {
+ target = true;
+ if (iequals(params.find(name)->second.atom, "false")) {
+ target = false;
+ } else if(iequals(params.find(name)->second.atom, "off")) {
+ target = false;
+ } else if(iequals(params.find(name)->second.atom, "no")) {
+ target = false;
+ } else if(iequals(params.find(name)->second.atom, "0")) {
+ target = false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T> static bool getParam(params_t params, const std::string& name, std::list<T>& target) {
+ if (params.find(name) != params.end()) {
+ std::pair<params_t::iterator, params_t::iterator> rangeIter = params.equal_range(name);
+ while(rangeIter.first != rangeIter.second) {
+ target.push_back(boost::lexical_cast<T>(rangeIter.first->second.atom));
+ rangeIter.first++;
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+#ifdef SWIGIMPORTED
+protected:
+#endif
+
+ std::string raw;
+ std::string xml;
+ std::string name;
+ Type eventType;
+ std::string origin;
+ std::string origintype;
+ Arabica::DOM::Node<std::string> dom;
+ std::string sendid;
+ bool hideSendId;
+ std::string invokeid;
+ Data data;
+ std::string content;
+ std::map<std::string, Data> namelist;
+ std::multimap<std::string, Data> params;
+
+ friend USCXML_API std::ostream& operator<< (std::ostream& os, const Event& event);
+};
+
+USCXML_API std::ostream& operator<< (std::ostream& os, const Event& event);
+
+}
+
+#endif /* end of include guard: EVENT_H_6174D929 */
diff --git a/src/uscxml/messages/InvokeRequest.cpp b/src/uscxml/messages/InvokeRequest.cpp
new file mode 100644
index 0000000..a39c8c6
--- /dev/null
+++ b/src/uscxml/messages/InvokeRequest.cpp
@@ -0,0 +1,91 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/messages/InvokeRequest.h"
+#include <DOM/Simple/DOMImplementation.hpp>
+#include <DOM/Document.hpp>
+#include <DOM/io/Stream.hpp>
+
+namespace uscxml {
+
+std::string InvokeRequest::toXMLString() {
+ std::stringstream ss;
+ ss << toDocument();
+ return ss.str();
+}
+
+Arabica::DOM::Document<std::string> InvokeRequest::toDocument() {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> document = Event::toDocument();
+ Arabica::DOM::Element<std::string> scxmlMsg = document.getDocumentElement();
+
+ scxmlMsg.setAttribute("invokeid", invokeid);
+
+ return document;
+}
+
+InvokeRequest InvokeRequest::fromXML(const std::string& xmlString) {
+ Event::fromXML(xmlString);
+ return InvokeRequest();
+}
+
+std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq) {
+
+ std::string indent;
+ for (int i = 0; i < _dataIndentation; i++) {
+ indent += " ";
+ }
+
+ os << indent << "InvokeReq" << (invokeReq.autoForward ? " with autoforward" : "") << std::endl;
+
+ if (invokeReq.type.size() > 0)
+ os << indent << " type: " << invokeReq.type << std::endl;
+
+ if (invokeReq.src.size() > 0)
+ os<< indent << " src: " << invokeReq.src << std::endl;
+
+ if (invokeReq.namelist.size() > 0) {
+ os << indent << " namelist: " << std::endl;
+ InvokeRequest::namelist_t::const_iterator namelistIter = invokeReq.namelist.begin();
+ while(namelistIter != invokeReq.namelist.end()) {
+ os << indent << " " << namelistIter->first << ": " << namelistIter->second << std::endl;
+ namelistIter++;
+ }
+ }
+
+ if (invokeReq.params.size() > 0) {
+ os << indent << " params: " << std::endl;
+ InvokeRequest::params_t::const_iterator paramIter = invokeReq.params.begin();
+ while(paramIter != invokeReq.params.end()) {
+ os << indent << " " << paramIter->first << ": " << paramIter->second << std::endl;
+ paramIter++;
+ }
+ }
+
+ if (invokeReq.content.size() > 0)
+ os << indent << " content: " << invokeReq.content << std::endl;
+
+ _dataIndentation++;
+ os << (Event)invokeReq;
+ _dataIndentation--;
+ return os;
+
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/messages/InvokeRequest.h b/src/uscxml/messages/InvokeRequest.h
new file mode 100644
index 0000000..ac5f6f7
--- /dev/null
+++ b/src/uscxml/messages/InvokeRequest.h
@@ -0,0 +1,72 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef INVOKEREQUEST_H_BAF058E2
+#define INVOKEREQUEST_H_BAF058E2
+
+#include "uscxml/messages/Event.h"
+
+namespace uscxml {
+
+class USCXML_API InvokeRequest : public Event {
+public:
+ InvokeRequest(Event event) : Event(event) {}
+ InvokeRequest() {}
+
+ std::string getType() {
+ return type;
+ }
+ void setType(const std::string& type) {
+ this->type = type;
+ }
+
+ std::string getSource() {
+ return src;
+ }
+ void setSource(const std::string& src) {
+ this->src = src;
+ }
+
+ bool isAutoForwarded() {
+ return autoForward;
+ }
+ void setAutoForwarded(bool autoForward) {
+ this->autoForward = autoForward;
+ }
+
+ static InvokeRequest fromXML(const std::string& xmlString);
+ Arabica::DOM::Document<std::string> toDocument();
+ std::string toXMLString();
+
+#ifdef SWIGIMPORTED
+protected:
+#endif
+ std::string type;
+ std::string src;
+ bool autoForward;
+
+ friend USCXML_API std::ostream& operator<< (std::ostream& os, const InvokeRequest& sendReq);
+
+};
+
+USCXML_API std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq);
+
+}
+
+#endif /* end of include guard: INVOKEREQUEST_H_BAF058E2 */
diff --git a/src/uscxml/messages/SendRequest.cpp b/src/uscxml/messages/SendRequest.cpp
new file mode 100644
index 0000000..a8fbe13
--- /dev/null
+++ b/src/uscxml/messages/SendRequest.cpp
@@ -0,0 +1,135 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/messages/SendRequest.h"
+#include <DOM/Simple/DOMImplementation.hpp>
+#include <DOM/Document.hpp>
+#include <DOM/io/Stream.hpp>
+
+namespace uscxml {
+
+std::string SendRequest::toXMLString() {
+ std::stringstream ss;
+ ss << toDocument();
+ return ss.str();
+}
+
+Arabica::DOM::Document<std::string> SendRequest::toDocument() {
+ Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ Arabica::DOM::Document<std::string> document = Event::toDocument();
+ Arabica::DOM::Element<std::string> scxmlMsg = document.getDocumentElement();
+
+ // add params and namelist
+ if (params.size() > 0 || namelist.size() > 0) {
+ Arabica::DOM::NodeList<std::string> payload = scxmlMsg.getElementsByTagName("scxml:payload");
+ if (payload.getLength() == 0) {
+ Arabica::DOM::Element<std::string> payloadElem = document.createElementNS("http://www.w3.org/2005/07/scxml", "payload");
+ payloadElem.setPrefix("scxml");
+
+ scxmlMsg.appendChild(payloadElem);
+ }
+ Arabica::DOM::Node<std::string> payloadElem = scxmlMsg.getElementsByTagName("scxml:payload").item(0);
+
+ // add parameters
+ std::multimap<std::string, Data>::iterator paramIter = params.begin();
+ while(paramIter != params.end()) {
+ Arabica::DOM::Element<std::string> propertyElem = document.createElementNS("http://www.w3.org/2005/07/scxml", "property");
+ propertyElem.setPrefix("scxml");
+
+ propertyElem.setAttribute("name", paramIter->first);
+ // this is simplified - Data might be more elaborate than a simple string atom
+ Arabica::DOM::Text<std::string> textElem = document.createTextNode(paramIter->second.atom);
+ propertyElem.appendChild(textElem);
+ payloadElem.appendChild(propertyElem);
+ paramIter++;
+ }
+
+ // add namelist elements
+ std::map<std::string, Data>::iterator namelistIter = namelist.begin();
+ while(namelistIter != namelist.end()) {
+ Arabica::DOM::Element<std::string> propertyElem = document.createElementNS("http://www.w3.org/2005/07/scxml", "property");
+ propertyElem.setPrefix("scxml");
+
+ propertyElem.setAttribute("name", namelistIter->first);
+ // this is simplified - Data might be more elaborate than a simple string atom
+ Arabica::DOM::Text<std::string> textElem = document.createTextNode(namelistIter->second.atom);
+ propertyElem.appendChild(textElem);
+ payloadElem.appendChild(propertyElem);
+ namelistIter++;
+ }
+
+ }
+
+ scxmlMsg.setAttribute("sendid", sendid);
+
+ return document;
+}
+
+SendRequest SendRequest::fromXML(const std::string& xmlString) {
+ Event::fromXML(xmlString);
+ return SendRequest();
+}
+
+std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) {
+
+ std::string indent;
+ for (int i = 0; i < _dataIndentation; i++) {
+ indent += " ";
+ }
+
+ os << indent << "SendReq" << std::endl;
+
+ if (sendReq.target.size() > 0)
+ os << indent << " target: " << sendReq.target << std::endl;
+
+ if (sendReq.type.size() > 0)
+ os << indent << " type: " << sendReq.type << std::endl;
+
+ if (sendReq.delayMs > 0)
+ os<< indent << " delay: " << sendReq.delayMs << std::endl;
+
+ if (sendReq.namelist.size() > 0) {
+ os << indent << " namelist: " << std::endl;
+ SendRequest::namelist_t::const_iterator namelistIter = sendReq.namelist.begin();
+ while(namelistIter != sendReq.namelist.end()) {
+ os << indent << " " << namelistIter->first << ": " << namelistIter->second << std::endl;
+ namelistIter++;
+ }
+ }
+
+ if (sendReq.params.size() > 0) {
+ os << indent << " params: " << std::endl;
+ SendRequest::params_t::const_iterator paramIter = sendReq.params.begin();
+ while(paramIter != sendReq.params.end()) {
+ os << indent << " " << paramIter->first << ": " << paramIter->second << std::endl;
+ paramIter++;
+ }
+ }
+
+ if (sendReq.content.size() > 0)
+ os << indent << " content: " << sendReq.content << std::endl;
+
+ _dataIndentation++;
+ os << (Event)sendReq;
+ _dataIndentation--;
+ return os;
+
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/messages/SendRequest.h b/src/uscxml/messages/SendRequest.h
new file mode 100644
index 0000000..6bc3d91
--- /dev/null
+++ b/src/uscxml/messages/SendRequest.h
@@ -0,0 +1,72 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef SENDREQUEST_H_86B0F6A0
+#define SENDREQUEST_H_86B0F6A0
+
+#include "uscxml/messages/Event.h"
+
+namespace uscxml {
+
+class USCXML_API SendRequest : public Event {
+public:
+ SendRequest() {}
+ SendRequest(Event event) : Event(event) {}
+
+ std::string getTarget() {
+ return target;
+ }
+ void setTarget(const std::string& target) {
+ this->target = target;
+ }
+
+ std::string getType() {
+ return type;
+ }
+ void setType(const std::string& type) {
+ this->type = type;
+ }
+
+ uint32_t getDelayMs() {
+ return delayMs;
+ }
+ void setDelayMs(uint32_t delayMs) {
+ this->delayMs = delayMs;
+ }
+
+ static SendRequest fromXML(const std::string& xmlString);
+ Arabica::DOM::Document<std::string> toDocument();
+ std::string toXMLString();
+
+#ifdef SWIGIMPORTED
+protected:
+#endif
+ std::string target;
+ std::string type;
+ uint32_t delayMs;
+
+ friend USCXML_API std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq);
+
+};
+
+USCXML_API std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq);
+
+}
+
+#endif /* end of include guard: SENDREQUEST_H_86B0F6A0 */