/** * @file * @author 2012-2013 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 . * @endcond */ #include "MMIMessages.h" #include #include #include #include #include #include #define STRING_ATTR_OR_EXPR(element, name)\ (element.hasAttributeNS(nameSpace, "name##Expr") && interpreter ? \ interpreter->getDataModel().evalAsString(element.getAttributeNS(nameSpace, "name##Expr")) : \ (element.hasAttributeNS(nameSpace, #name) ? element.getAttributeNS(nameSpace, #name) : "") \ ) #define FIND_EVENT_NODE(node)\ while (node) {\ if (node.getNodeType() == Node_base::ELEMENT_NODE) {\ if (boost::iequals(node.getLocalName(), "MMI")) {\ node = node.getFirstChild();\ continue;\ } else {\ break;\ }\ }\ node = node.getNextSibling();\ }\ namespace uscxml { using namespace Arabica::DOM; std::string MMIEvent::nameSpace = "http://www.w3.org/2008/04/mmi-arch"; MMIEvent::Type MMIEvent::getType(Arabica::DOM::Node node) { if (!node || node.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) return INVALID; // MMI container? if (boost::iequals(node.getLocalName(), "MMI")) { node = node.getFirstChild(); if (!node) return INVALID; while(node.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) { node = node.getNextSibling(); if (!node) return INVALID; } } if (boost::iequals(node.getLocalName(), "NEWCONTEXTREQUEST")) return NEWCONTEXTREQUEST; if (boost::iequals(node.getLocalName(), "NEWCONTEXTRESPONSE")) return NEWCONTEXTRESPONSE; if (boost::iequals(node.getLocalName(), "PREPAREREQUEST")) return PREPAREREQUEST; if (boost::iequals(node.getLocalName(), "PREPARERESPONSE")) return PREPARERESPONSE; if (boost::iequals(node.getLocalName(), "STARTREQUEST")) return STARTREQUEST; if (boost::iequals(node.getLocalName(), "STARTRESPONSE")) return STARTRESPONSE; if (boost::iequals(node.getLocalName(), "DONENOTIFICATION")) return DONENOTIFICATION; if (boost::iequals(node.getLocalName(), "CANCELREQUEST")) return CANCELREQUEST; if (boost::iequals(node.getLocalName(), "CANCELRESPONSE")) return CANCELRESPONSE; if (boost::iequals(node.getLocalName(), "PAUSEREQUEST")) return PAUSEREQUEST; if (boost::iequals(node.getLocalName(), "PAUSERESPONSE")) return PAUSERESPONSE; if (boost::iequals(node.getLocalName(), "RESUMEREQUEST")) return RESUMEREQUEST; if (boost::iequals(node.getLocalName(), "RESUMERESPONSE")) return RESUMERESPONSE; if (boost::iequals(node.getLocalName(), "EXTENSIONNOTIFICATION")) return EXTENSIONNOTIFICATION; if (boost::iequals(node.getLocalName(), "CLEARCONTEXTREQUEST")) return CLEARCONTEXTREQUEST; if (boost::iequals(node.getLocalName(), "CLEARCONTEXTRESPONSE")) return CLEARCONTEXTRESPONSE; if (boost::iequals(node.getLocalName(), "STATUSREQUEST")) return STATUSREQUEST; if (boost::iequals(node.getLocalName(), "STATUSRESPONSE")) return STATUSRESPONSE; return INVALID; } Arabica::DOM::Document MMIEvent::toXML(bool encapsulateInMMI) const { Arabica::DOM::DOMImplementation domFactory = Arabica::SimpleDOM::DOMImplementation::getDOMImplementation(); Document doc = domFactory.createDocument(nameSpace, "", 0); Element msgElem = doc.createElementNS(nameSpace, tagName); msgElem.setAttributeNS(nameSpace, "Source", source); msgElem.setAttributeNS(nameSpace, "Target", target); msgElem.setAttributeNS(nameSpace, "RequestID", requestId); if (data.size() > 0) { Element dataElem = doc.createElementNS(nameSpace, "Data"); Text textElem = doc.createTextNode(data); dataElem.appendChild(textElem); msgElem.appendChild(dataElem); } else if (dataDOM) { Element dataElem = doc.createElementNS(nameSpace, "Data"); Node importNode = doc.importNode(dataDOM, true); dataElem.appendChild(importNode); msgElem.appendChild(dataElem); } if (encapsulateInMMI) { Element mmiElem = doc.createElementNS(nameSpace, "mmi"); mmiElem.appendChild(msgElem); doc.appendChild(mmiElem); } else { doc.appendChild(msgElem); } return doc; } Arabica::DOM::Document ContextualizedRequest::toXML(bool encapsulateInMMI) const { Document doc = MMIEvent::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); msgElem.setAttributeNS(nameSpace, "Context", context); return doc; } Arabica::DOM::Document ContentRequest::toXML(bool encapsulateInMMI) const { Document doc = ContextualizedRequest::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); if (contentURL.href.size() > 0) { Element contentURLElem = doc.createElementNS(nameSpace, "ContentURL"); contentURLElem.setAttributeNS(nameSpace, "href", contentURL.href); contentURLElem.setAttributeNS(nameSpace, "fetchtimeout", contentURL.fetchTimeout); contentURLElem.setAttributeNS(nameSpace, "max-age", contentURL.maxAge); msgElem.appendChild(contentURLElem); } else if (contentDOM) { Element contentElem = doc.createElementNS(nameSpace, "Content"); Node importNode = doc.importNode(contentDOM, true); contentElem.appendChild(importNode); msgElem.appendChild(contentElem); } else if (content.size() > 0) { Element contentElem = doc.createElementNS(nameSpace, "Content"); Text textElem = doc.createTextNode(content); contentElem.appendChild(textElem); msgElem.appendChild(contentElem); } return doc; } Arabica::DOM::Document ExtensionNotification::toXML(bool encapsulateInMMI) const { Document doc = ContextualizedRequest::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); msgElem.setAttributeNS(nameSpace, "Name", name); return doc; } Arabica::DOM::Document StatusResponse::toXML(bool encapsulateInMMI) const { Document doc = ContextualizedRequest::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); if (status == ALIVE) { msgElem.setAttributeNS(nameSpace, "Status", "alive"); } else if(status == DEAD) { msgElem.setAttributeNS(nameSpace, "Status", "dead"); } else if(status == FAILURE) { msgElem.setAttributeNS(nameSpace, "Status", "failure"); } else if(status == SUCCESS) { msgElem.setAttributeNS(nameSpace, "Status", "success"); } return doc; } Arabica::DOM::Document StatusInfoResponse::toXML(bool encapsulateInMMI) const { Document doc = StatusResponse::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); Element statusInfoElem = doc.createElementNS(nameSpace, "StatusInfo"); Text statusInfoText = doc.createTextNode(statusInfo); statusInfoElem.appendChild(statusInfoText); msgElem.appendChild(statusInfoElem); return doc; } Arabica::DOM::Document StatusRequest::toXML(bool encapsulateInMMI) const { Document doc = ContextualizedRequest::toXML(encapsulateInMMI); Element msgElem = Element(doc.getDocumentElement().getFirstChild()); if (automaticUpdate) { msgElem.setAttributeNS(nameSpace, "RequestAutomaticUpdate", "true"); } else { msgElem.setAttributeNS(nameSpace, "RequestAutomaticUpdate", "false"); } return doc; } MMIEvent MMIEvent::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { MMIEvent msg; FIND_EVENT_NODE(node); Element msgElem(node); msg.source = STRING_ATTR_OR_EXPR(msgElem, Source); msg.target = STRING_ATTR_OR_EXPR(msgElem, Target); // msg.data = STRING_ATTR_OR_EXPR(msgElem, Data); msg.requestId = STRING_ATTR_OR_EXPR(msgElem, RequestID); msg.tagName = msgElem.getLocalName(); Element dataElem; node = msgElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) dataElem = Element(node); if (dataElem && boost::iequals(dataElem.getLocalName(), "data")) break; node = node.getNextSibling(); } if (dataElem && boost::iequals(dataElem.getLocalName(), "data") && dataElem.getFirstChild()) { node = dataElem.getFirstChild(); if (node.getNodeType() == Arabica::DOM::Node_base::ELEMENT_NODE) { msg.dataDOM = node; } else { std::stringstream ss; ss << node; msg.data = ss.str(); } } return msg; } MMIEvent::operator Event() const { Event ev; ev.setOriginType("mmi.event"); ev.setOrigin(source); ev.setRaw(data); ev.setSendId(requestId); if (data.length() > 0) { ev.initContent(data); } return ev; } ContextualizedRequest ContextualizedRequest::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { ContextualizedRequest msg(MMIEvent::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); msg.context = STRING_ATTR_OR_EXPR(msgElem, Context); return msg; } ContextualizedRequest::operator Event() const { Event ev = MMIEvent::operator Event(); // do we want to represent the context? It's the interpreters name already return ev; } ContentRequest ContentRequest::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { ContentRequest msg(ContextualizedRequest::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); Element contentElem; node = msgElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) { contentElem = Element(node); if (boost::iequals(contentElem.getLocalName(), "content") || boost::iequals(contentElem.getLocalName(), "contentURL")) break; } node = node.getNextSibling(); } if (contentElem) { if(boost::iequals(contentElem.getLocalName(), "content")) { std::stringstream ss; node = contentElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) { ss << node; break; } node = node.getNextSibling(); } msg.content = ss.str(); } else if(boost::iequals(contentElem.getLocalName(), "contentURL")) { msg.contentURL.href = STRING_ATTR_OR_EXPR(contentElem, href); msg.contentURL.maxAge = STRING_ATTR_OR_EXPR(contentElem, max-age); msg.contentURL.fetchTimeout = STRING_ATTR_OR_EXPR(contentElem, fetchtimeout); } } //msg.content = msgElem.getAttributeNS(nameSpace, "Context"); return msg; } ExtensionNotification ExtensionNotification::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { ExtensionNotification msg(ContextualizedRequest::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); msg.name = STRING_ATTR_OR_EXPR(msgElem, Name); msg.type = EXTENSIONNOTIFICATION; return msg; } ExtensionNotification::operator Event() const { Event ev = ContextualizedRequest::operator Event(); if (name.length() > 0) { ev.setName("mmi.extensionnotification." + name); } else { ev.setName("mmi.extensionnotification"); } return ev; } StatusResponse StatusResponse::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { StatusResponse msg(ContextualizedRequest::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); std::string status = STRING_ATTR_OR_EXPR(msgElem, Status); if (boost::iequals(status, "ALIVE")) { msg.status = ALIVE; } else if(boost::iequals(status, "DEAD")) { msg.status = DEAD; } else if(boost::iequals(status, "FAILURE")) { msg.status = FAILURE; } else if(boost::iequals(status, "SUCCESS")) { msg.status = SUCCESS; } else { msg.status = INVALID; } msg.type = STATUSRESPONSE; return msg; } StatusInfoResponse StatusInfoResponse::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { StatusInfoResponse msg(StatusResponse::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); Element statusInfoElem; node = msgElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) { statusInfoElem = Element(node); if (statusInfoElem && boost::iequals(statusInfoElem.getLocalName(), "statusInfo")) break; } node = node.getNextSibling(); } if (statusInfoElem && boost::iequals(statusInfoElem.getLocalName(), "statusInfo")) { node = statusInfoElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::TEXT_NODE) { msg.statusInfo = node.getNodeValue(); break; } node = node.getNextSibling(); } } return msg; } StatusRequest StatusRequest::fromXML(Arabica::DOM::Node node, InterpreterImpl* interpreter) { StatusRequest msg(ContextualizedRequest::fromXML(node, interpreter)); FIND_EVENT_NODE(node); Element msgElem(node); std::string autoUpdate = STRING_ATTR_OR_EXPR(msgElem, RequestAutomaticUpdate); if (boost::iequals(autoUpdate, "true")) { msg.automaticUpdate = true; } else if(boost::iequals(autoUpdate, "on")) { msg.automaticUpdate = true; } else if(boost::iequals(autoUpdate, "yes")) { msg.automaticUpdate = true; } else if(boost::iequals(autoUpdate, "1")) { msg.automaticUpdate = true; } else { msg.automaticUpdate = false; } msg.type = STATUSREQUEST; return msg; } }