summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-12-05 16:20:11 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2014-12-05 16:20:11 (GMT)
commit93f8cb376e6e496f0194d1e0657081354434da96 (patch)
tree551d4b37708cb983b73432029f370b605d76da29 /src/uscxml
parenta5a139f46438148901ea6627b73d1bf6ae39b346 (diff)
downloaduscxml-93f8cb376e6e496f0194d1e0657081354434da96.zip
uscxml-93f8cb376e6e496f0194d1e0657081354434da96.tar.gz
uscxml-93f8cb376e6e496f0194d1e0657081354434da96.tar.bz2
Support for xinclude
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/Interpreter.cpp50
-rw-r--r--src/uscxml/Interpreter.h9
-rw-r--r--src/uscxml/debug/DebugSession.cpp2
-rw-r--r--src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp4
-rw-r--r--src/uscxml/transform/ChartToPromela.cpp15
5 files changed, 55 insertions, 25 deletions
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 4dabcb9..cb780df 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -372,7 +372,7 @@ InterpreterImpl::InterpreterImpl() {
#endif
}
-Interpreter Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom, const NameSpaceInfo& nameSpaceInfo) {
+Interpreter Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom, const NameSpaceInfo& nameSpaceInfo, const std::string& sourceURI) {
tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex);
boost::shared_ptr<INTERPRETER_IMPL> interpreterImpl = boost::shared_ptr<INTERPRETER_IMPL>(new INTERPRETER_IMPL);
Interpreter interpreter(interpreterImpl);
@@ -397,14 +397,14 @@ Interpreter Interpreter::fromDOM(const Arabica::DOM::Document<std::string>& dom,
return interpreter;
}
-Interpreter Interpreter::fromXML(const std::string& xml) {
+Interpreter Interpreter::fromXML(const std::string& xml, const std::string& sourceURI) {
std::stringstream* ss = new std::stringstream();
(*ss) << xml;
// we need an auto_ptr for arabica to assume ownership
std::auto_ptr<std::istream> ssPtr(ss);
Arabica::SAX::InputSource<std::string> inputSource;
inputSource.setByteStream(ssPtr);
- return fromInputSource(inputSource);
+ return fromInputSource(inputSource, sourceURI);
}
@@ -421,7 +421,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
if (iequals(absUrl.scheme(), "file")) {
Arabica::SAX::InputSource<std::string> inputSource;
inputSource.setSystemId(absUrl.asString());
- interpreter = fromInputSource(inputSource);
+ interpreter = fromInputSource(inputSource, absUrl);
} else {
// use curl for everything !file - even for http as arabica won't follow redirects
std::stringstream ss;
@@ -429,20 +429,17 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
if (absUrl.downloadFailed()) {
ERROR_COMMUNICATION_THROW("Downloading SCXML document from '" + absUrl.asString() + "' failed");
}
- interpreter = fromXML(ss.str());
+ interpreter = fromXML(ss.str(), absUrl);
}
// try to establish URI root for relative src attributes in document
- if (interpreter) {
- interpreter._impl->_baseURI = URL::asBaseURL(absUrl);
- interpreter._impl->_sourceURI = absUrl;
- } else {
+ if (!interpreter) {
ERROR_PLATFORM_THROW("Cannot create interpreter from URI '" + absUrl.asString() + "'");
}
return interpreter;
}
-Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source) {
+Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>& source, const std::string& sourceUri) {
tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex);
// remove old instances
@@ -463,6 +460,9 @@ Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>&
if (parser.parse(source) && parser.getDocument() && parser.getDocument().hasChildNodes()) {
interpreterImpl->setNameSpaceInfo(parser.nameSpace);
interpreterImpl->_document = parser.getDocument();
+ interpreterImpl->_baseURI = URL::asBaseURL(sourceUri);
+ interpreterImpl->_sourceURI = sourceUri;
+
interpreterImpl->setupDOM();
} else {
if (parser.errorsReported()) {
@@ -1224,6 +1224,8 @@ void InterpreterImpl::setupDOM() {
ERROR_PLATFORM_THROW("Interpreter has no DOM");
}
+ resolveXIncludes();
+
// find scxml element
if (!_scxml) {
NodeList<std::string> scxmls;
@@ -1284,6 +1286,34 @@ void InterpreterImpl::setupDOM() {
_domIsSetup = true;
}
+void InterpreterImpl::resolveXIncludes() {
+ std::string xIncludeNS = _nsInfo.getXMLPrefixForNS("http://www.w3.org/2001/XInclude");
+ if (xIncludeNS.size() > 0) {
+ Arabica::XPath::NodeSet<std::string> xincludes = _xpath.evaluate("//" + xIncludeNS + "include", _document.getDocumentElement()).asNodeSet();
+ for (int i = 0; i < xincludes.size(); i++) {
+ if (HAS_ATTR_CAST(xincludes[i], "href")) {
+ URL src(ATTR_CAST(xincludes[i], "href"));
+ if (!src.isAbsolute()) {
+ if (!src.toAbsolute(_baseURI)) {
+ LOG(ERROR) << "Cannot resolve relative URL '" << ATTR_CAST(xincludes[i], "href") << "' to absolute URL via base URL '" << _baseURI << "'";
+ continue;
+ }
+ }
+ NameSpacingParser xiParser = NameSpacingParser::fromXML(src.getInContent());
+ if (xiParser.errorsReported()) {
+ ERROR_PLATFORM_THROW(xiParser.errors());
+ } else {
+ // import DOM
+ Node<std::string> imported = _document.importNode(xiParser.getDocument().getDocumentElement(), true);
+ xincludes[i].getParentNode().insertBefore(imported, xincludes[i]);
+ xincludes[i].getParentNode().removeChild(xincludes[i]);
+ }
+ }
+ }
+ }
+
+}
+
void InterpreterImpl::init() {
// make sure we have a factory if none was set before
if (_factory == NULL)
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index d6da7bd..d962083 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -458,6 +458,7 @@ protected:
InterpreterImpl();
void init();
void setupDOM();
+ void resolveXIncludes();
virtual void setupIOProcessors();
std::list<InterpreterIssue> validate();
@@ -583,8 +584,10 @@ protected:
class USCXML_API Interpreter {
public:
static Interpreter fromDOM(const Arabica::DOM::Document<std::string>& dom,
- const NameSpaceInfo& nameSpaceInfo);
- static Interpreter fromXML(const std::string& xml);
+ const NameSpaceInfo& nameSpaceInfo,
+ const std::string& sourceURI);
+ static Interpreter fromXML(const std::string& xml,
+ const std::string& sourceURI);
static Interpreter fromURI(const std::string& uri);
static Interpreter fromClone(const Interpreter& other);
@@ -815,7 +818,7 @@ protected:
return _impl->setInvokeRequest(req);
}
- static Interpreter fromInputSource(Arabica::SAX::InputSource<std::string>& source);
+ static Interpreter fromInputSource(Arabica::SAX::InputSource<std::string>& source, const std::string& sourceUri);
boost::shared_ptr<InterpreterImpl> _impl;
static std::map<std::string, boost::weak_ptr<InterpreterImpl> > _instances;
diff --git a/src/uscxml/debug/DebugSession.cpp b/src/uscxml/debug/DebugSession.cpp
index c73f53e..d81be51 100644
--- a/src/uscxml/debug/DebugSession.cpp
+++ b/src/uscxml/debug/DebugSession.cpp
@@ -106,7 +106,7 @@ Data DebugSession::debugPrepare(const Data& data) {
_isAttached = false;
if (data.hasKey("xml")) {
- _interpreter = Interpreter::fromXML(data.at("xml").atom);
+ _interpreter = Interpreter::fromXML(data.at("xml").atom, "");
} else if (data.hasKey("url")) {
_interpreter = Interpreter::fromURI(data.at("url").atom);
} else {
diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
index 5a447c4..84e5520 100644
--- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp
@@ -82,9 +82,9 @@ void USCXMLInvoker::invoke(const InvokeRequest& req) {
Arabica::DOM::Node<std::string> newNode = dom.importNode(req.dom, true);
dom.appendChild(newNode);
// TODO: where do we get the namespace from?
- _invokedInterpreter = Interpreter::fromDOM(dom, std::map<std::string, std::string>());
+ _invokedInterpreter = Interpreter::fromDOM(dom, _interpreter->getNameSpaceInfo(), _interpreter->getSourceURI());
} else if (req.content.size() > 0) {
- _invokedInterpreter = Interpreter::fromXML(req.content);
+ _invokedInterpreter = Interpreter::fromXML(req.content, _interpreter->getSourceURI());
} else {
LOG(ERROR) << "Cannot invoke nested SCXML interpreter, neither src attribute nor content nor DOM is given";
}
diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp
index 9d297ad..7676a37 100644
--- a/src/uscxml/transform/ChartToPromela.cpp
+++ b/src/uscxml/transform/ChartToPromela.cpp
@@ -2041,6 +2041,7 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) {
if (_analyzer->getTypes().types.find("_ioprocessors") != _analyzer->getTypes().types.end()) {
stream << "hidden _ioprocessors_t " << _prefix << "_ioprocessors;" << std::endl;
+ _varInitializers.push_front("_ioprocessors.scxml.location = " + (_invokerid.size() > 0 ? _analyzer->macroForLiteral(_invokerid) : "1") + ";");
}
if (_prefix.size() == 0 || _prefix == "MAIN_") {
@@ -2110,21 +2111,17 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) {
type = type.substr(0, bracketPos);
}
std::string decl = type + " " + _prefix + identifier + arrSize;
+ stream << decl << ";" << std::endl;
if (arrSize.length() > 0) {
- stream << decl << ";" << std::endl;
_varInitializers.push_back(value);
} else {
- stream << decl;
if (expression.length() > 0) {
// id and expr given
- stream << " = " << ADAPT_SRC(boost::trim_copy(expression)) << ";" << std::endl;
+ _varInitializers.push_back(identifier + " = " + boost::trim_copy(expression) + ";");
} else if (value.length() > 0) {
// id and text content given
- stream << " = " << ADAPT_SRC(value) << ";" << std::endl;
- } else {
- // only id given
- stream << ";" << std::endl;
+ _varInitializers.push_back(identifier + " = " + value + ";");
}
}
} else if (value.length() > 0) {
@@ -2625,7 +2622,7 @@ void ChartToPromela::writeMain(std::ostream& stream) {
if (_varInitializers.size() > 0) {
std::list<std::string>::iterator initIter = _varInitializers.begin();
while(initIter != _varInitializers.end()) {
- stream << ADAPT_SRC(beautifyIndentation(*initIter));
+ stream << ADAPT_SRC(beautifyIndentation(*initIter)) << std::endl;
initIter++;
}
stream << std::endl;
@@ -2717,7 +2714,7 @@ void ChartToPromela::initNodes() {
Node<std::string> importRoot = nestedDoc.importNode(nestedRoot[0], true);
nestedDoc.appendChild(importRoot);
- nested = Interpreter::fromDOM(nestedDoc, _nsInfo);
+ nested = Interpreter::fromDOM(nestedDoc, _nsInfo, _sourceURI);
}
// std::cout << invokes[i] << std::endl;