summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/swig/csharp/org/uscxml/InterpreterException.cs2
-rw-r--r--src/bindings/swig/csharp/uscxml.i147
-rw-r--r--src/bindings/swig/java/org/uscxml/Data.java89
-rw-r--r--src/bindings/swig/java/uscxml.i211
-rw-r--r--src/bindings/swig/uscxml_beautify.i97
-rw-r--r--src/bindings/swig/uscxml_ignores.i6
-rw-r--r--src/bindings/swig/wrapped/WrappedDataModel.h1
-rw-r--r--src/bindings/swig/wrapped/WrappedExecutableContent.h2
-rw-r--r--src/bindings/swig/wrapped/WrappedIOProcessor.h1
-rw-r--r--src/bindings/swig/wrapped/WrappedInvoker.h1
-rw-r--r--src/uscxml/Factory.cpp53
-rw-r--r--src/uscxml/Interpreter.cpp82
-rw-r--r--src/uscxml/Interpreter.h5
-rw-r--r--src/uscxml/URL.cpp18
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp178
-rw-r--r--src/uscxml/messages/Data.h8
-rw-r--r--src/uscxml/messages/Event.cpp2
-rw-r--r--src/uscxml/messages/Event.h57
-rw-r--r--src/uscxml/messages/InvokeRequest.cpp2
-rw-r--r--src/uscxml/messages/SendRequest.cpp4
-rw-r--r--src/uscxml/plugins/DataModel.h4
-rw-r--r--src/uscxml/plugins/EventHandler.h4
-rw-r--r--src/uscxml/plugins/Invoker.h5
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp31
-rw-r--r--src/uscxml/plugins/datamodel/null/NULLDataModel.cpp5
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp10
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp30
-rw-r--r--src/uscxml/plugins/datamodel/promela/PromelaParser.cpp13
-rw-r--r--src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp54
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp4
-rw-r--r--src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp13
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp4
32 files changed, 676 insertions, 467 deletions
diff --git a/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs b/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
index f86dc0e..38430d8 100644
--- a/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
+++ b/src/bindings/swig/csharp/org/uscxml/InterpreterException.cs
@@ -1,5 +1,5 @@
namespace org.uscxml {
- class InterpreterException : System.ApplicationException {
+ public class InterpreterException : System.ApplicationException {
public InterpreterException(string message)
: base(message) {
}
diff --git a/src/bindings/swig/csharp/uscxml.i b/src/bindings/swig/csharp/uscxml.i
index 988c541..8e9a297 100644
--- a/src/bindings/swig/csharp/uscxml.i
+++ b/src/bindings/swig/csharp/uscxml.i
@@ -12,10 +12,19 @@
%include <boost_shared_ptr.i>
+// these are needed at least for the templates to work
typedef uscxml::Data Data;
typedef uscxml::Event Event;
typedef uscxml::InvokeRequest InvokeRequest;
typedef uscxml::SendRequest SendRequest;
+typedef uscxml::Invoker Invoker;
+typedef uscxml::IOProcessor IOProcessor;
+typedef uscxml::DataModel DataModel;
+typedef uscxml::ExecutableContent ExecutableContent;
+typedef uscxml::InvokerImpl InvokerImpl;
+typedef uscxml::IOProcessorImpl IOProcessorImpl;
+typedef uscxml::DataModelImpl DataModelImpl;
+typedef uscxml::ExecutableContentImpl ExecutableContentImpl;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
@@ -54,6 +63,7 @@ typedef uscxml::SendRequest SendRequest;
using namespace uscxml;
using namespace Arabica::DOM;
+// the wrapped* C++ classes get rid of DOM nodes and provide more easily wrapped base classes
#include "../wrapped/WrappedInvoker.cpp"
#include "../wrapped/WrappedDataModel.cpp"
#include "../wrapped/WrappedExecutableContent.cpp"
@@ -125,11 +135,139 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%include "../uscxml_ignores.i"
-%rename Data DataNative;
+//***********************************************
+// Beautify important classes
+//***********************************************
%include "../uscxml_beautify.i"
+%rename(getCompoundNative) uscxml::Data::getCompound();
+%rename(getArrayNative) uscxml::Data::getArray();
+%rename(setCompoundNative) uscxml::Data::setCompound(const std::map<std::string, Data>&);
+%rename(setArrayNative) uscxml::Data::setArray(const std::list<Data>&);
+%csmethodmodifiers uscxml::Data::getCompound() "private";
+%csmethodmodifiers uscxml::Data::getArray() "private";
+%csmethodmodifiers uscxml::Data::setCompound(const std::map<std::string, Data>&) "private";
+%csmethodmodifiers uscxml::Data::setArray(const std::list<Data>&) "private";
+%csmethodmodifiers uscxml::Data::getCompoundKeys() "private";
+
+%typemap(csimports) uscxml::Data %{
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+%}
+
+%typemap(cscode) uscxml::Data %{
+ public Data(List<Data> arr) : this() {
+ setArray(arr);
+ }
+
+ public Data(Dictionary<string, Data> compound) : this() {
+ setCompound(compound);
+ }
+
+ public Dictionary<string, Data> getCompound() {
+ Dictionary<string, Data> compound = new Dictionary<string, Data>();
+ DataMap dataMap = getCompoundNative();
+ StringVector dataMapKeys = getCompoundKeys();
+ for (int i = 0; i < dataMapKeys.Count; i++) {
+ compound[dataMapKeys[i]] = dataMap[dataMapKeys[i]];
+ }
+ return compound;
+ }
+
+ public void setCompound(Dictionary<string, Data> compound) {
+ DataMap dataMap = new DataMap();
+ foreach(KeyValuePair<string, Data> entry in compound) {
+ dataMap.Add(entry);
+ }
+ setCompoundNative(dataMap);
+ }
+
+ public List<Data> getArray() {
+ List<Data> arr = new List<Data>();
+ DataList dataList = getArrayNative();
+ for (int i = 0; i < dataList.size(); i++) {
+ arr.Add(dataList.get(i));
+ }
+ return arr;
+ }
+
+ public void setArray(List<Data> arr) {
+ DataList dataList = new DataList();
+ foreach (Data data in arr) {
+ dataList.add(data);
+ }
+ setArrayNative(dataList);
+ }
+
+%}
+
+%rename(getNameListNative) uscxml::Event::getNameList();
+%rename(getParamsNative) uscxml::Event::getParams();
+%rename(setNameListNative) uscxml::Event::setNameList(const std::map<std::string, Data>&);
+%rename(setParamsNative) uscxml::Event::setParams(const std::multimap<std::string, Data>&);
+%csmethodmodifiers uscxml::Event::getNameList() "private";
+%csmethodmodifiers uscxml::Event::getNameListKeys() "private";
+%csmethodmodifiers uscxml::Event::getParams() "private";
+%csmethodmodifiers uscxml::Event::setNameList(const std::map<std::string, Data>&) "private";
+%csmethodmodifiers uscxml::Event::setParams(const std::multimap<std::string, Data>&) "private";
+
+%typemap(csimports) uscxml::Event %{
+ using System;
+ using System.Collections.Generic;
+ using System.Runtime.InteropServices;
+%}
+
+%typemap(cscode) uscxml::Event %{
+ public Dictionary<string, List<Data> > getParams() {
+ Dictionary<string, List<Data>> parameters = new Dictionary<string, List<Data>>();
+ ParamMap paramMap = getParamMap();
+
+ foreach (KeyValuePair<string, DataList> entry in paramMap) {
+ DataList dataList = entry.Value;
+ List<Data> paramList = new List<Data>();
+ for (int i = 0; i < dataList.size(); i++) {
+ Data data = dataList.get(i);
+ paramList.Add(data);
+ }
+ parameters.Add(entry.Key, paramList);
+ }
+ return parameters;
+ }
+
+ public void setParams(Dictionary<string, List<Data>> parameters) {
+ ParamMap paramMap = new ParamMap();
+ foreach(KeyValuePair<string, List<Data>> entry in parameters) {
+ DataList dataList = new DataList();
+ foreach (Data data in entry.Value) {
+ dataList.add(data);
+ }
+ paramMap.Add(entry.Key, dataList);
+ }
+ setParamMap(paramMap);
+ }
+
+ public Dictionary<string, Data> getNameList() {
+ Dictionary<string, Data> nameList = new Dictionary<string, Data>();
+ DataMap nameListMap = getNameListNative();
+ StringVector nameListMapKeys = getNameListKeys();
+ for (int i = 0; i < nameListMapKeys.Count; i++) {
+ nameList[nameListMapKeys[i]] = nameListMap[nameListMapKeys[i]];
+ }
+ return nameList;
+ }
+
+ public void setNameList(Dictionary<string, Data> nameList) {
+ DataMap dataMap = new DataMap();
+ foreach (KeyValuePair<string, Data> entry in nameList) {
+ dataMap.Add(entry);
+ }
+ setNameListNative(dataMap);
+ }
+%}
+
//***********************************************
// Parse the header file to generate wrappers
//***********************************************
@@ -164,8 +302,7 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%template(StringSet) std::set<std::string>;
%template(StringVector) std::vector<std::string>;
%template(StringList) std::list<std::string>;
-%template(ParamPair) std::pair<std::string, uscxml::Data>;
-%template(ParamPairVector) std::vector<std::pair<std::string, uscxml::Data> >;
-%template(IOProcMap) std::map<std::string, uscxml::IOProcessor>;
-%template(InvokerMap) std::map<std::string, uscxml::Invoker>;
+%template(ParamMap) std::map<std::string, std::list<uscxml::Data> >;
+%template(IOProcMap) std::map<std::string, IOProcessor>;
+%template(InvokerMap) std::map<std::string, Invoker>;
%template(ParentQueue) uscxml::concurrency::BlockingQueue<uscxml::SendRequest>;
diff --git a/src/bindings/swig/java/org/uscxml/Data.java b/src/bindings/swig/java/org/uscxml/Data.java
deleted file mode 100644
index 7781f47..0000000
--- a/src/bindings/swig/java/org/uscxml/Data.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.uscxml;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-public class Data {
- public Map<String, Data> compound = new HashMap<String, Data>();
- public List<Data> array = new LinkedList<Data>();
- public String atom;
- public Type type = Type.INTERPRETED;
-
- public enum Type {
- VERBATIM, INTERPRETED
- }
-
- public static Data fromJSON(String jsonString) {
- return new Data(DataNative.fromJSON(jsonString));
- }
-
- public Data() {
- }
-
- public Data(String atom, Data.Type type) {
- this.atom = atom;
- this.type = type;
- }
-
- public Data(DataNative nativeData) {
- if (!nativeData.getCompound().empty()) {
- // data is a key value compound
- StringVector keys = nativeData.getCompundKeys();
- for(int i = 0; i < keys.size(); i++) {
- this.compound.put(keys.get(i), new Data(nativeData.getCompound().get(keys.get(i))));
- }
- } else if (!nativeData.getArray().isEmpty()) {
- // data is an array
- for (int i = 0; i < nativeData.getArray().size(); i++) {
- this.array.add(new Data(nativeData.getArray().get(i)));
- }
- } else {
- // data is a single atom
- this.atom = nativeData.getAtom();
- if (nativeData.getType() == DataNative.Type.INTERPRETED) {
- this.type = Type.INTERPRETED;
- } else {
- this.type = Type.VERBATIM;
- }
- }
- }
-
- @Override
- public String toString() {
- return toJSON();
- }
-
- public String toJSON() {
- DataNative nativeData = toNative(this);
- return DataNative.toJSON(nativeData);
- }
-
- public static DataNative toNative(Data data) {
- DataNative nativeData = new DataNative();
- //nativeData.swigCMemOwn = false;
- if (data.compound != null && !data.compound.isEmpty()) {
- DataMap nativeDataMap = new DataMap();
- for (String key : data.compound.keySet()) {
- nativeDataMap.set(key, toNative(data.compound.get(key)));
- }
- nativeData.setCompound(nativeDataMap);
- } else if (data.array != null && !data.array.isEmpty()) {
- DataList nativeDataList = new DataList();
- for (Data item : data.array) {
- nativeDataList.add(toNative(item));
- }
- nativeData.setArray(nativeDataList);
- } else if (data.atom != null) {
- nativeData.setAtom(data.atom);
- if (data.type == Type.INTERPRETED) {
- nativeData.setType(DataNative.Type.INTERPRETED);
- } else {
- nativeData.setType(DataNative.Type.VERBATIM);
- }
- }
- return nativeData;
- }
-
-}
diff --git a/src/bindings/swig/java/uscxml.i b/src/bindings/swig/java/uscxml.i
index 880b02d..cb760e4 100644
--- a/src/bindings/swig/java/uscxml.i
+++ b/src/bindings/swig/java/uscxml.i
@@ -12,10 +12,19 @@
%include <boost_shared_ptr.i>
+// these are needed at least for the templates to work
typedef uscxml::Data Data;
typedef uscxml::Event Event;
typedef uscxml::InvokeRequest InvokeRequest;
typedef uscxml::SendRequest SendRequest;
+typedef uscxml::Invoker Invoker;
+typedef uscxml::IOProcessor IOProcessor;
+typedef uscxml::DataModel DataModel;
+typedef uscxml::ExecutableContent ExecutableContent;
+typedef uscxml::InvokerImpl InvokerImpl;
+typedef uscxml::IOProcessorImpl IOProcessorImpl;
+typedef uscxml::DataModelImpl DataModelImpl;
+typedef uscxml::ExecutableContentImpl ExecutableContentImpl;
%feature("director") uscxml::WrappedInvoker;
%feature("director") uscxml::WrappedDataModel;
@@ -33,7 +42,6 @@ typedef uscxml::SendRequest SendRequest;
%rename(equals) operator==;
%rename(isValid) operator bool;
-
//**************************************************
// This ends up in the generated wrapper code
//**************************************************
@@ -54,6 +62,7 @@ typedef uscxml::SendRequest SendRequest;
using namespace uscxml;
using namespace Arabica::DOM;
+// the wrapped* C++ classes get rid of DOM nodes and provide more easily wrapped base classes
#include "../wrapped/WrappedInvoker.cpp"
#include "../wrapped/WrappedDataModel.cpp"
#include "../wrapped/WrappedExecutableContent.cpp"
@@ -86,11 +95,202 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%include "../uscxml_ignores.i"
-%rename Data DataNative;
+// see http://swig.org/Doc2.0/Java.html#Java_date_marshalling
+%define BEAUTIFY_NATIVE( MATCH, WRAPPER, NATIVE )
+
+%rename WRAPPER NATIVE;
+
+%typemap(jstype) const MATCH & "WRAPPER"
+%typemap(jstype) MATCH "WRAPPER"
+
+%typemap(javain,
+ pre=" NATIVE temp$javainput = $javainput.toNative();",
+ pgcppname="temp$javainput") const MATCH &
+ "$javaclassname.getCPtr(temp$javainput)"
+
+ %typemap(javain,
+ pre=" NATIVE temp$javainput = $javainput.toNative();",
+ pgcppname="temp$javainput") MATCH
+ "$javaclassname.getCPtr(temp$javainput)"
+
+%typemap(javaout) const MATCH & {
+ NATIVE nativeData = new NATIVE($jnicall, $owner);
+ return new WRAPPER(nativeData);
+}
+
+%typemap(javaout) MATCH {
+ NATIVE nativeData = new NATIVE($jnicall, $owner);
+ return new WRAPPER(nativeData);
+}
+
+%typemap(javadirectorout) MATCH "NATIVE.getCPtr($javacall.toNative())"
+
+%typemap(javadirectorin) MATCH "WRAPPER.fromNative(new NATIVE($jniinput, false))";
+%typemap(javadirectorin) const MATCH & "WRAPPER.fromNative(new NATIVE($jniinput, false))";
+
+%typemap(directorin,descriptor="L/org/uscxml/"##"WRAPPER;") const MATCH & "*(MATCH **)&$input = (MATCH *) &$1;"
+
+%typemap(directorout) MATCH ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Unexpected null return for type $1_type");
+ return $null;
+ }
+ $result = *argp; %}
+
+%enddef
+
+/*
+// not used as it will not work for directors :(
+BEAUTIFY_NATIVE(uscxml::Data, Data, DataNative);
+BEAUTIFY_NATIVE(uscxml::Event, Event, EventNative);
+BEAUTIFY_NATIVE(uscxml::SendRequest, SendRequest, SendRequestNative);
+BEAUTIFY_NATIVE(uscxml::InvokeRequest, InvokeRequest, InvokeRequestNative);
+*/
+
+
+//***********************************************
+// Beautify important classes
+//***********************************************
%include "../uscxml_beautify.i"
+%rename(getCompoundNative) uscxml::Data::getCompound();
+%rename(getArrayNative) uscxml::Data::getArray();
+%rename(setCompoundNative) uscxml::Data::setCompound(const std::map<std::string, Data>&);
+%rename(setArrayNative) uscxml::Data::setArray(const std::list<Data>&);
+%javamethodmodifiers uscxml::Data::getCompound() "private";
+%javamethodmodifiers uscxml::Data::getArray() "private";
+%javamethodmodifiers uscxml::Data::setCompound(const std::map<std::string, Data>&) "private";
+%javamethodmodifiers uscxml::Data::setArray(const std::list<Data>&) "private";
+%javamethodmodifiers uscxml::Data::getCompoundKeys() "private";
+
+%typemap(javaimports) uscxml::Data %{
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+%}
+
+%typemap(javacode) uscxml::Data %{
+ public Data(Map<String, Data> compound) {
+ this(uscxmlNativeJavaJNI.new_Data__SWIG_0(), true);
+ setCompound(compound);
+ }
+
+ public Data(List<Data> array) {
+ this(uscxmlNativeJavaJNI.new_Data__SWIG_0(), true);
+ setArray(array);
+ }
+
+ public Map<String, Data> getCompound() {
+ Map<String, Data> compound = new HashMap<String, Data>();
+ DataMap dataMap = getCompoundNative();
+ StringVector dataMapKeys = getCompoundKeys();
+ for (int i = 0; i < dataMapKeys.size(); i++) {
+ compound.put(dataMapKeys.get(i), dataMap.get(dataMapKeys.get(i)));
+ }
+ return compound;
+ }
+
+ public void setCompound(Map<String, Data> compound) {
+ DataMap dataMap = new DataMap();
+ for (String key : compound.keySet()) {
+ dataMap.set(key, compound.get(key));
+ }
+ setCompoundNative(dataMap);
+ }
+
+ public List<Data> getArray() {
+ List<Data> array = new LinkedList<Data>();
+ DataList dataList = getArrayNative();
+ for (int i = 0; i < dataList.size(); i++) {
+ array.add(dataList.get(i));
+ }
+ return array;
+ }
+
+ public void setArray(List<Data> array) {
+ DataList dataList = new DataList();
+ for (Data data : array) {
+ dataList.add(data);
+ }
+ setArrayNative(dataList);
+ }
+
+%}
+
+%rename(getNameListNative) uscxml::Event::getNameList();
+%rename(getParamstNative) uscxml::Event::getParams();
+%rename(setNameListNative) uscxml::Event::setNameList(const std::map<std::string, Data>&);
+%rename(setParamsNative) uscxml::Event::setParams(const std::multimap<std::string, Data>&);
+%javamethodmodifiers uscxml::Event::getNameList() "private";
+%javamethodmodifiers uscxml::Event::getNameListKeys() "private";
+%javamethodmodifiers uscxml::Event::getParams() "private";
+%javamethodmodifiers uscxml::Event::setNameList(const std::map<std::string, Data>&) "private";
+%javamethodmodifiers uscxml::Event::setParams(const std::multimap<std::string, Data>&) "private";
+
+%typemap(javaimports) uscxml::Event %{
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+%}
+
+%typemap(javacode) uscxml::Event %{
+ public Map<String, List<Data>> getParams() {
+ Map<String, List<Data>> params = new HashMap<String, List<Data>>();
+ ParamMap paramMap = getParamMap();
+ StringVector paramMapKeys = getParamMapKeys();
+
+ for (int i = 0; i < paramMapKeys.size(); i++) {
+ String key = paramMapKeys.get(i);
+ DataList dataList = paramMap.get(key);
+
+ for (int j = 0; j < dataList.size(); j++) {
+ Data data = dataList.get(j);
+ if (!params.containsKey(key))
+ params.put(key, new LinkedList<Data>());
+ params.get(key).add(data);
+ }
+ }
+ return params;
+ }
+
+ public void setParams(Map<String, List<Data>> params) {
+ ParamMap paramMap = new ParamMap();
+ for (String key : params.keySet()) {
+ DataList datalist = new DataList();
+ for (Data data : params.get(key)) {
+ datalist.add(data);
+ }
+ paramMap.set(key, datalist);
+ }
+ setParamMap(paramMap);
+ }
+
+ public Map<String, Data> getNameList() {
+ Map<String, Data> namelist = new HashMap<String, Data>();
+ StringVector nameMapKeys = getNameListKeys();
+ DataMap nameMap = getNameListNative();
+
+ for (int i = 0; i < nameMapKeys.size(); i++) {
+ namelist.put(nameMapKeys.get(i), nameMap.get(nameMapKeys.get(i)));
+ }
+ return namelist;
+ }
+
+ public void setNameList(Map<String, Data> namelist) {
+ DataMap nameListMap = new DataMap();
+ for (String key : namelist.keySet()) {
+ nameListMap.set(key, namelist.get(key));
+ }
+ setNameListNative(nameListMap);
+ }
+%}
+
+
//***********************************************
// Parse the header file to generate wrappers
//***********************************************
@@ -125,8 +325,7 @@ WRAP_THROW_EXCEPTION(uscxml::Interpreter::interpret);
%template(StringSet) std::set<std::string>;
%template(StringVector) std::vector<std::string>;
%template(StringList) std::list<std::string>;
-%template(ParamPair) std::pair<std::string, uscxml::Data>;
-%template(ParamPairVector) std::vector<std::pair<std::string, uscxml::Data> >;
-%template(IOProcMap) std::map<std::string, uscxml::IOProcessor>;
-%template(InvokerMap) std::map<std::string, uscxml::Invoker>;
+%template(ParamMap) std::map<std::string, std::list<uscxml::Data> >;
+%template(IOProcMap) std::map<std::string, IOProcessor>;
+%template(InvokerMap) std::map<std::string, Invoker>;
%template(ParentQueue) uscxml::concurrency::BlockingQueue<uscxml::SendRequest>;
diff --git a/src/bindings/swig/uscxml_beautify.i b/src/bindings/swig/uscxml_beautify.i
index 8a53fbb..ac3ed44 100644
--- a/src/bindings/swig/uscxml_beautify.i
+++ b/src/bindings/swig/uscxml_beautify.i
@@ -9,15 +9,76 @@
%rename(NativeInterpreterMonitor) InterpreterMonitor;
%rename(InterpreterMonitor) WrappedInterpreterMonitor;
-%extend uscxml::Event {
- std::vector<std::pair<std::string, Data> > getParamPairs() {
- std::vector<std::pair<std::string, Data> > pairs;
- std::multimap<std::string, Data>::iterator paramPairIter = self->getParams().begin();
+%extend uscxml::Event {
+/* std::vector<std::pair<std::string, uscxml::Data> > getParamPairs() {
+ std::vector<std::pair<std::string, Data> > pairs;
+ std::multimap<std::string, Data>::iterator paramPairIter = self->getParams().begin();
+ while(paramPairIter != self->getParams().end()) {
+ pairs.push_back(*paramPairIter);
+ paramPairIter++;
+ }
+ return pairs;
+ }
+
+ void setParamPairs(const std::vector<std::pair<std::string, uscxml::Data> >& pairs) {
+ std::multimap<std::string, Data> params;
+ std::vector<std::pair<std::string, Data> >::const_iterator pairIter = pairs.begin();
+ while(pairIter != pairs.end()) {
+ params.insert(std::make_pair(pairIter->first, pairIter->second));
+ pairIter++;
+ }
+ self->setParams(params);
+ }
+*/
+
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+
+ std::map<std::string, std::list<uscxml::Data> > getParamMap() {
+ std::map<std::string, std::list<uscxml::Data> > paramMap;
+ std::multimap<std::string, Data>::const_iterator paramPairIter = self->getParams().begin();
while(paramPairIter != self->getParams().end()) {
- pairs.push_back(*paramPairIter);
+ paramMap[paramPairIter->first].push_back(paramPairIter->second);
paramPairIter++;
}
- return pairs;
+ return paramMap;
+ }
+
+ std::vector<std::string> getParamMapKeys() {
+ std::vector<std::string> keys;
+ for(std::multimap<std::string, Data>::const_iterator iter = self->getParams().begin();
+ iter != self->getParams().end();
+ iter = self->getParams().upper_bound(iter->first)) {
+ keys.push_back(iter->first);
+ }
+ return keys;
+ }
+
+ void setParamMap(const std::map<std::string, std::list<uscxml::Data> >& paramMap) {
+ std::multimap<std::string, Data> params;
+ std::map<std::string, std::list<uscxml::Data> >::const_iterator mapIter = paramMap.begin();
+ while(mapIter != paramMap.end()) {
+ std::list<uscxml::Data>::const_iterator dataIter = mapIter->second.begin();
+ while(dataIter != mapIter->second.end()) {
+ params.insert(std::make_pair(mapIter->first, *dataIter));
+ dataIter++;
+ }
+ mapIter++;
+ }
+ self->setParams(params);
+ }
+
+ std::vector<std::string> getNameListKeys() {
+ std::vector<std::string> keys;
+ std::map<std::string, Data>::const_iterator iter = self->getNameList().begin();
+ while(iter != self->getNameList().end()) {
+ keys.push_back(iter->first);
+ iter++;
+ }
+ return keys;
}
};
@@ -66,7 +127,13 @@
};
%extend uscxml::Data {
- std::vector<std::string> getCompundKeys() {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+
+ std::vector<std::string> getCompoundKeys() {
std::vector<std::string> keys;
std::map<std::string, Data>::const_iterator iter = self->compound.begin();
while(iter != self->compound.end()) {
@@ -76,3 +143,19 @@
return keys;
}
};
+
+%extend uscxml::SendRequest {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+};
+
+%extend uscxml::InvokeRequest {
+ std::string toString() {
+ std::stringstream ss;
+ ss << *self;
+ return ss.str();
+ }
+}; \ No newline at end of file
diff --git a/src/bindings/swig/uscxml_ignores.i b/src/bindings/swig/uscxml_ignores.i
index c5bf88b..d54dae2 100644
--- a/src/bindings/swig/uscxml_ignores.i
+++ b/src/bindings/swig/uscxml_ignores.i
@@ -21,7 +21,6 @@
%ignore uscxml::EventHandler::getElement;
%ignore uscxml::EventHandler::runOnMainThread;
-
%ignore uscxml::NameSpaceInfo::NameSpaceInfo(const std::map<std::string, std::string>&);
%ignore uscxml::NameSpaceInfo::NameSpaceInfo(const NameSpaceInfo&);
%ignore uscxml::NameSpaceInfo::setPrefix(Arabica::DOM::Element<std::string>);
@@ -180,6 +179,11 @@
%ignore uscxml::Event::toDocument();
%ignore uscxml::Event::getParams();
%ignore uscxml::Event::getParam;
+%ignore uscxml::Event::setParams;
+
+%ignore uscxml::SendRequest::fromXML;
+%ignore uscxml::InvokeRequest::fromXML;
+
// Data
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h
index 013f22c..e1b29af 100644
--- a/src/bindings/swig/wrapped/WrappedDataModel.h
+++ b/src/bindings/swig/wrapped/WrappedDataModel.h
@@ -46,6 +46,7 @@ public:
_interpreter = interpreter->shared_from_this();
return boost::shared_ptr<DataModelImpl>(create(_interpreter));
}
+
virtual std::list<std::string> getNames() {
return std::list<std::string>();
};
diff --git a/src/bindings/swig/wrapped/WrappedExecutableContent.h b/src/bindings/swig/wrapped/WrappedExecutableContent.h
index e00704a..b1ce4f9 100644
--- a/src/bindings/swig/wrapped/WrappedExecutableContent.h
+++ b/src/bindings/swig/wrapped/WrappedExecutableContent.h
@@ -72,11 +72,9 @@ public:
}
virtual void enterElement(const std::string& node) {
-
}
virtual void exitElement(const std::string& node) {
-
}
private:
diff --git a/src/bindings/swig/wrapped/WrappedIOProcessor.h b/src/bindings/swig/wrapped/WrappedIOProcessor.h
index 1d134dc..b4e4938 100644
--- a/src/bindings/swig/wrapped/WrappedIOProcessor.h
+++ b/src/bindings/swig/wrapped/WrappedIOProcessor.h
@@ -47,6 +47,7 @@ public:
_interpreter = interpreter->shared_from_this();
return boost::shared_ptr<IOProcessorImpl>(create(_interpreter));
}
+
virtual std::list<std::string> getNames() {
return std::list<std::string>();
};
diff --git a/src/bindings/swig/wrapped/WrappedInvoker.h b/src/bindings/swig/wrapped/WrappedInvoker.h
index b3ff200..6251c6e 100644
--- a/src/bindings/swig/wrapped/WrappedInvoker.h
+++ b/src/bindings/swig/wrapped/WrappedInvoker.h
@@ -50,6 +50,7 @@ public:
virtual void send(const SendRequest& req) {}
virtual void invoke(const InvokeRequest& req) {}
+ virtual void uninvoke() {}
virtual WrappedInvoker* create(Interpreter interpreter) {
return new WrappedInvoker();
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 3556aba..22482e6 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -516,7 +516,7 @@ boost::shared_ptr<InvokerImpl> Factory::createInvoker(const std::string& type, I
if (_parentFactory) {
return _parentFactory->createInvoker(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " Invoker known";
+ ERROR_EXECUTION_THROW("No Invoker named '" + type + "' known");
}
return boost::shared_ptr<InvokerImpl>();
@@ -538,7 +538,7 @@ boost::shared_ptr<DataModelImpl> Factory::createDataModel(const std::string& typ
if (_parentFactory) {
return _parentFactory->createDataModel(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " Datamodel known";
+ ERROR_EXECUTION_THROW("No Datamodel name '" + type + "' known");
}
return boost::shared_ptr<DataModelImpl>();
@@ -559,7 +559,7 @@ boost::shared_ptr<IOProcessorImpl> Factory::createIOProcessor(const std::string&
if (_parentFactory) {
return _parentFactory->createIOProcessor(type, interpreter);
} else {
- LOG(ERROR) << "No " << type << " IOProcessor known";
+ ERROR_EXECUTION_THROW("No IOProcessor named '" + type + "' known");
}
return boost::shared_ptr<IOProcessorImpl>();
@@ -578,7 +578,7 @@ boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const
if (_parentFactory) {
return _parentFactory->createExecutableContent(localName, nameSpace, interpreter);
} else {
- LOG(ERROR) << "Executable content " << localName << " in " << actualNameSpace << " not available in factory";
+ ERROR_EXECUTION_THROW("No Executable content name '" + localName + "' in namespace '" + actualNameSpace + "' known");
}
return boost::shared_ptr<ExecutableContentImpl>();
@@ -654,51 +654,32 @@ Factory* Factory::getInstance() {
}
void EventHandlerImpl::returnErrorExecution(const std::string& cause) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(cause, Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
- returnEvent(exceptionEvent);
+ ERROR_EXECUTION(exc, cause);
+ returnEvent(exc);
}
-void EventHandlerImpl::returnErrorPlatform(const std::string& cause) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(cause, Data::VERBATIM);
- exceptionEvent.name = "error.platform";
- exceptionEvent.eventType = Event::PLATFORM;
- returnEvent(exceptionEvent);
+void EventHandlerImpl::returnErrorCommunication(const std::string& cause) {
+ ERROR_COMMUNICATION(exc, cause);
+ returnEvent(exc);
}
-void EventHandlerImpl::returnEvent(Event& event) {
+void EventHandlerImpl::returnEvent(Event& event, bool external) {
if (event.invokeid.length() == 0)
event.invokeid = _invokeId;
if (event.eventType == 0)
- event.eventType = Event::EXTERNAL;
+ event.eventType = (external ? Event::EXTERNAL : Event::INTERNAL);
if (event.origin.length() == 0)
event.origin = "#_" + _invokeId;
if (event.origintype.length() == 0)
event.origintype = _type;
-
- _interpreter->receive(event);
-}
-
-void DataModelImpl::throwErrorExecution(const std::string& cause) {
- uscxml::Event exc;
- exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
- exc.name = "error.execution";
- exc.eventType = uscxml::Event::PLATFORM;
- throw exc;
-}
-
-void DataModelImpl::throwErrorPlatform(const std::string& cause) {
- uscxml::Event exc;
- exc.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM);
- exc.name = "error.platform";
- exc.eventType = uscxml::Event::PLATFORM;
- throw exc;
+
+ if (external) {
+ _interpreter->receive(event);
+ } else {
+ _interpreter->receiveInternal(event);
+ }
}
-
Factory* Factory::_instance = NULL;
std::string Factory::_defaultPluginPath;
} \ No newline at end of file
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 22fb79e..47a6182 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -83,6 +83,7 @@
#define VALID_FROM_MACROSTEPPED(newState) ( \
newState == USCXML_DESTROYED || \
newState == USCXML_MICROSTEPPED || \
+ newState == USCXML_MACROSTEPPED || \
newState == USCXML_IDLE || \
newState == USCXML_FINISHED \
)
@@ -96,14 +97,7 @@
#define VALID_FROM_FINISHED(newState) ( \
newState == USCXML_DESTROYED || \
newState == USCXML_INSTANTIATED \
-)
-
-#define THROW_ERROR_PLATFORM(msg) \
- Event e; \
- e.name = "error.platform"; \
- e.data.compound["cause"] = Data(msg, Data::VERBATIM); \
- throw e; \
-
+)
/// macro to catch exceptions in executeContent
#define CATCH_AND_DISTRIBUTE(msg) \
@@ -113,6 +107,7 @@ catch (Event e) {\
throw(e);\
} else {\
e.name = "error.execution";\
+ e.data.compound["cause"] = uscxml::Data(msg, uscxml::Data::VERBATIM); \
e.eventType = Event::PLATFORM;\
receiveInternal(e);\
}\
@@ -120,11 +115,14 @@ catch (Event e) {\
#define CATCH_AND_DISTRIBUTE2(msg, node) \
catch (Event e) {\
- LOG(ERROR) << msg << " " << DOMUtils::xPathForNode(node) << ":" << std::endl << e << std::endl;\
+ std::string xpathPos = DOMUtils::xPathForNode(node); \
+ LOG(ERROR) << msg << " " << xpathPos << ":" << std::endl << e << std::endl;\
if (rethrow) {\
throw(e);\
} else {\
e.name = "error.execution";\
+ e.data.compound["cause"] = uscxml::Data(msg, uscxml::Data::VERBATIM); \
+ e.data.compound["xpath"] = uscxml::Data(xpathPos, uscxml::Data::VERBATIM); \
e.eventType = Event::PLATFORM;\
e.dom = node;\
receiveInternal(e);\
@@ -394,7 +392,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
URL absUrl(uri);
if (!absUrl.isAbsolute()) {
if (!absUrl.toAbsoluteCwd()) {
- THROW_ERROR_PLATFORM("Given URL is not absolute or does not have file schema");
+ ERROR_COMMUNICATION_THROW("URL is not absolute or does not have file schema");
}
}
@@ -416,7 +414,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
std::stringstream ss;
ss << absUrl;
if (absUrl.downloadFailed()) {
- THROW_ERROR_PLATFORM("Downloading SCXML document from " + absUrl.asString() + " failed");
+ ERROR_COMMUNICATION_THROW("Downloading SCXML document from '" + absUrl.asString() + "' failed");
}
interpreter = fromXML(ss.str());
}
@@ -426,7 +424,7 @@ Interpreter Interpreter::fromURI(const std::string& uri) {
interpreter._impl->_baseURI = URL::asBaseURL(absUrl);
interpreter._impl->_sourceURI = absUrl;
} else {
- THROW_ERROR_PLATFORM("Cannot create interpreter from URI " + absUrl.asString() + "'");
+ ERROR_PLATFORM_THROW("Cannot create interpreter from URI '" + absUrl.asString() + "'");
}
return interpreter;
}
@@ -454,9 +452,9 @@ Interpreter Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string>&
interpreterImpl->_document = parser.getDocument();
} else {
if (parser.errorsReported()) {
- THROW_ERROR_PLATFORM(parser.errors())
+ ERROR_PLATFORM_THROW(parser.errors())
} else {
- THROW_ERROR_PLATFORM("Failed to create interpreter");
+ ERROR_PLATFORM_THROW("Failed to create interpreter");
// interpreterImpl->setInterpreterState(USCXML_FAULTED, parser.errors());
}
}
@@ -680,11 +678,13 @@ void InterpreterImpl::reset() {
_internalQueue.clear();
_historyValue.clear();
+ _currEvent = Event();
_alreadyEntered = NodeSet<std::string>();
_configuration = NodeSet<std::string>();
_topLevelFinalReached = false;
_isInitialized = false;
-
+ _stable = false;
+
setInterpreterState(USCXML_INSTANTIATED);
}
@@ -693,9 +693,7 @@ void InterpreterImpl::setupAndNormalizeDOM() {
return;
if (!_document) {
- Event error("error.platform");
- error.data.compound["cause"] = Data("Interpreter has no DOM", Data::VERBATIM);
- throw error;
+ ERROR_PLATFORM_THROW("Interpreter has no DOM");
}
// find scxml element
@@ -707,9 +705,7 @@ void InterpreterImpl::setupAndNormalizeDOM() {
}
if (scxmls.getLength() == 0) {
- Event error("error.platform");
- error.data.compound["cause"] = Data("Cannot find SCXML element in DOM", Data::VERBATIM);
- throw error;
+ ERROR_PLATFORM_THROW("Cannot find SCXML element in DOM");
}
_scxml = (Arabica::DOM::Element<std::string>)scxmls.item(0);
@@ -777,12 +773,8 @@ void InterpreterImpl::init() {
// instantiate datamodel
if (HAS_ATTR(_scxml, "datamodel")) {
+ // might throw
_dataModel = _factory->createDataModel(ATTR(_scxml, "datamodel"), this);
- if (!_dataModel) {
- Event e;
- e.data.compound["cause"] = Data("Cannot instantiate datamodel", Data::VERBATIM);
- throw e;
- }
} else {
_dataModel = _factory->createDataModel("null", this);
}
@@ -1264,9 +1256,8 @@ void InterpreterImpl::delayedSend(void* userdata, std::string eventName) {
* If the SCXML Processor does not support the type that is specified, it
* must place the event error.execution on the internal event queue.
*/
- Event exceptionEvent("error.execution", Event::PLATFORM);
-// exceptionEvent.sendid = sendReq.sendid;
- INSTANCE->receiveInternal(exceptionEvent);
+ ERROR_EXECUTION(exc, "Unsupported type '" + sendReq.type + "' with send element");
+ INSTANCE->receiveInternal(exc);
}
assert(INSTANCE->_sendIds.find(sendReq.sendid) != INSTANCE->_sendIds.end());
@@ -1372,7 +1363,12 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) {
if (invokeReq.type.size() == 0)
invokeReq.type = "http://www.w3.org/TR/scxml/";
- Invoker invoker(_factory->createInvoker(invokeReq.type, this));
+ Invoker invoker;
+ try {
+ invoker = _factory->createInvoker(invokeReq.type, this);
+ } catch (Event e) {
+ receiveInternal(e);
+ }
if (invoker) {
tthread::lock_guard<tthread::recursive_mutex> lock(_pluginMutex);
try {
@@ -1439,7 +1435,7 @@ void InterpreterImpl::cancelInvoke(const Arabica::DOM::Node<std::string>& elemen
}
USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId)
-
+ _invokers[invokeId].uninvoke();
_invokers.erase(invokeId);
USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element<std::string>(element), invokeId)
@@ -1689,8 +1685,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
try {
if (!_dataModel.isDeclared(ATTR(content, "location"))) {
// test 286, 331
- LOG(ERROR) << "Assigning to undeclared location '" << ATTR(content, "location") << "' not allowed." << std::endl;
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Assigning to undeclared location '" + ATTR(content, "location") + "' not allowed.");
} else {
Node<std::string> dom;
std::string text;
@@ -1745,7 +1740,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
try {
_dataModel.eval((Element<std::string>)content, srcContent.str());
}
- CATCH_AND_DISTRIBUTE("Syntax error while executing script element from '" << ATTR(content, "src") << "':")
+ CATCH_AND_DISTRIBUTE("Syntax error while executing script element from '" + ATTR(content, "src") + "':")
} else {
if (content.hasChildNodes()) {
// search for the text node with the actual script
@@ -1791,16 +1786,9 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
// --- Custom Executable Content
ExecutableContent execContent;
if (_executableContent.find(content) == _executableContent.end()) {
- execContent = _factory->createExecutableContent(content.getLocalName(), content.getNamespaceURI(), this);
- if (!execContent) {
- LOG(ERROR) << "No custom executable content known for element '"
- << content.getLocalName() << "' in namespace '" << content.getNamespaceURI() << "'";
- return;
- }
- _executableContent[content] = execContent;
- } else {
- execContent = _executableContent[content];
+ _executableContent[content] = _factory->createExecutableContent(content.getLocalName(), content.getNamespaceURI(), this);
}
+ execContent = _executableContent[content];
execContent.enterElement(content);
if (execContent.processChildren()) {
@@ -2005,13 +1993,8 @@ Arabica::DOM::Node<std::string> InterpreterImpl::getState(const std::string& sta
if (target.size() > 0)
goto FOUND;
- LOG(ERROR) << "No state with id " << stateId << " found!";
{
- Event ev;
- ev.name = "error.execution";
- ev.eventType = Event::PLATFORM;
- ev.data.compound["cause"] = Data("No state with id " + stateId + " found", Data::VERBATIM);
- throw ev;
+ ERROR_EXECUTION_THROW("No state with id '" + stateId + "' found");
}
FOUND:
if (target.size() > 0) {
@@ -2403,6 +2386,7 @@ void InterpreterImpl::setupIOProcessors() {
continue;
}
+ // this might throw error.execution
_ioProcessors[ioProcIter->first] = _factory->createIOProcessor(ioProcIter->first, this);
_ioProcessors[ioProcIter->first].setType(ioProcIter->first);
_ioProcessors[ioProcIter->first].setInterpreter(this);
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index a07d9af..cf281b5 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -46,6 +46,11 @@
#include "uscxml/plugins/Invoker.h"
#include "uscxml/plugins/ExecutableContent.h"
+#define ERROR_PLATFORM_THROW(msg) \
+ Event e; \
+ e.name = "error.platform"; \
+ e.data.compound["cause"] = Data(msg, Data::VERBATIM); \
+ throw e; \
#define USCXML_MONITOR_CATCH(callback) \
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index aaf4cde..08135fd 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -364,19 +364,19 @@ const void URLImpl::download(bool blocking) {
_condVar.wait(_mutex); // wait for notification
}
if (_hasFailed) {
- Event exception;
- exception.name = "error.communication";
- exception.data = URL(shared_from_this());
+ ERROR_COMMUNICATION(exc, _error);
+ exc.data = URL(shared_from_this());
if (_error.length() > 0)
- exception.data.compound["reason"] = Data(_error, Data::VERBATIM);
- throw exception;
+ exc.data.compound["cause"] = Data(_error, Data::VERBATIM);
+ throw exc;
}
if (iequals(scheme(), "http")) {
if (_statusCode.size() > 0 && boost::lexical_cast<int>(_statusCode) > 400) {
- Event exception;
- exception.name = "error.communication";
- exception.data = URL(shared_from_this());
- throw exception;
+ ERROR_COMMUNICATION(exc, _error);
+ exc.data = URL(shared_from_this());
+ if (_error.length() > 0)
+ exc.data.compound["cause"] = Data(_error, Data::VERBATIM);
+ throw exc;
}
}
}
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index dd23a87..048adf9 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -135,21 +135,23 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
NodeSet<std::string> initialTransitions = getDocumentInitialTransitions();
assert(initialTransitions.size() > 0);
enterStates(initialTransitions);
+ setInterpreterState(USCXML_MICROSTEPPED);
}
- _stable = false;
-
// are there spontaneous transitions?
- enabledTransitions = selectEventlessTransitions();
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
+ if (!_stable) {
+ enabledTransitions = selectEventlessTransitions();
+ if (!enabledTransitions.empty()) {
+ // test 403b
+ enabledTransitions.to_document_order();
+ microstep(enabledTransitions);
- setInterpreterState(USCXML_MICROSTEPPED);
- return _state;
+ setInterpreterState(USCXML_MICROSTEPPED);
+ return _state;
+ }
+ _stable = true;
}
-
+
// test415
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
@@ -158,6 +160,7 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
if (!_internalQueue.empty()) {
_currEvent = _internalQueue.front();
_internalQueue.pop_front();
+ _stable = false;
USCXML_MONITOR_CALLBACK2(beforeProcessingEvent, _currEvent)
@@ -178,14 +181,15 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
} else {
_stable = true;
}
- // even if we did nothing - count as microstep
- setInterpreterState(USCXML_MICROSTEPPED);
+
+ if (_state != USCXML_MACROSTEPPED && _state != USCXML_IDLE)
+ USCXML_MONITOR_CALLBACK(onStableConfiguration)
+
+ setInterpreterState(USCXML_MACROSTEPPED);
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
- setInterpreterState(USCXML_MACROSTEPPED);
- USCXML_MONITOR_CALLBACK(onStableConfiguration)
// when we reach a stable configuration, invoke
for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
@@ -227,7 +231,8 @@ InterpreterState InterpreterDraft6::step(int waitForMS = 0) {
_currEvent = _externalQueue.pop();
_currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
-
+ _stable = false;
+
if (_topLevelFinalReached)
goto EXIT_INTERPRETER;
@@ -350,149 +355,6 @@ void InterpreterDraft6::stabilize() {
}
-#if 0
-void InterpreterDraft6::mainEventLoop() {
-
- while(_running) {
- NodeSet<std::string> enabledTransitions;
- _stable = false;
-
- // Here we handle eventless transitions and transitions
- // triggered by internal events until machine is stable
- while(_running && !_stable) {
-#if VERBOSE
- std::cout << "Configuration: ";
- for (int i = 0; i < _configuration.size(); i++) {
- std::cout << ATTR(_configuration[i], "id") << ", ";
- }
- std::cout << std::endl;
-#endif
-
- enabledTransitions = selectEventlessTransitions();
- if (enabledTransitions.size() == 0) {
- if (_internalQueue.size() == 0) {
- _stable = true;
- } else {
- _currEvent = _internalQueue.front();
- _internalQueue.pop_front();
-#if VERBOSE
- std::cout << "Received internal event " << _currEvent.name << std::endl;
-#endif
-
- USCXML_MONITOR_CALLBACK(beforeProcessingEvent)
-
- if (_dataModel)
- _dataModel.setEvent(_currEvent);
- enabledTransitions = selectTransitions(_currEvent.name);
- }
- }
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
- }
- }
-
- for (unsigned int i = 0; i < _statesToInvoke.size(); i++) {
- NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]);
- for (unsigned int j = 0; j < invokes.size(); j++) {
- if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) {
- invoke(invokes[j]);
- }
- }
- }
- _statesToInvoke = NodeSet<std::string>();
-
- if (!_internalQueue.empty())
- continue;
-
- // assume that we have a legal configuration as soon as the internal queue is empty
- assert(hasLegalConfiguration());
-
- USCXML_MONITOR_CALLBACK(onStableConfiguration)
-
- _mutex.unlock();
-
- // whenever we have a stable configuration, run the mainThread hooks with 200fps
- while(_externalQueue.isEmpty() && _thread == NULL) {
- runOnMainThread(200);
- }
- _mutex.lock();
-
- while(_externalQueue.isEmpty()) {
- _condVar.wait(_mutex);
- }
- _currEvent = _externalQueue.pop();
-#if VERBOSE
- std::cout << "Received externalEvent event " << _currEvent.name << std::endl;
- if (_running && _currEvent.name == "unblock.and.die") {
- std::cout << "Still running " << this << std::endl;
- } else {
- std::cout << "Aborting " << this << std::endl;
- }
-#endif
- _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external
- if (!_running)
- goto EXIT_INTERPRETER;
-
- USCXML_MONITOR_CALLBACK(beforeProcessingEvent)
-
- if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId))
- break;
-
- if (_dataModel) {
- try {
- _dataModel.setEvent(_currEvent);
- } catch (Event e) {
- LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent;
- }
- }
- for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin();
- invokeIter != _invokers.end();
- invokeIter++) {
- if (iequals(invokeIter->first, _currEvent.invokeid)) {
- Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement());
- for (int k = 0; k < finalizes.size(); k++) {
- Element<std::string> finalizeElem = Element<std::string>(finalizes[k]);
- executeContent(finalizeElem);
- }
- }
- if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) {
- try {
- // do not autoforward to invokers that send to #_parent from the SCXML IO Processor!
- // Yes do so, see test229!
- // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"))
- invokeIter->second.send(_currEvent);
- } catch(...) {
- LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first;
- }
- }
- }
- enabledTransitions = selectTransitions(_currEvent.name);
- if (!enabledTransitions.empty()) {
- // test 403b
- enabledTransitions.to_document_order();
- microstep(enabledTransitions);
- }
- }
-
-EXIT_INTERPRETER:
- USCXML_MONITOR_CALLBACK(beforeCompletion)
-
- exitInterpreter();
- if (_sendQueue) {
- std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin();
- while(sendIter != _sendIds.end()) {
- _sendQueue->cancelEvent(sendIter->first);
- sendIter++;
- }
- }
-
- USCXML_MONITOR_CALLBACK(afterCompletion)
-
-}
-#endif
-
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectTransitions(const std::string& event) {
Arabica::XPath::NodeSet<std::string> enabledTransitions;
diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h
index bf13409..9b5bea7 100644
--- a/src/uscxml/messages/Data.h
+++ b/src/uscxml/messages/Data.h
@@ -141,6 +141,14 @@ public:
return data;
}
+ void put(std::string key, const Data& data) {
+ compound[key] = data;
+ }
+
+ void put(size_t index, const Data& data) {
+ this[index] = data;
+ }
+
bool operator==(const Data &other) const {
if (other.atom.size() != atom.size())
return false;
diff --git a/src/uscxml/messages/Event.cpp b/src/uscxml/messages/Event.cpp
index a3e6a20..f8a880f 100644
--- a/src/uscxml/messages/Event.cpp
+++ b/src/uscxml/messages/Event.cpp
@@ -155,6 +155,8 @@ std::ostream& operator<< (std::ostream& os, const Event& event) {
os << indent << " origin: " << event.origin << std::endl;
if (event.origintype.size() > 0)
os << indent << " origintype: " << event.origintype << std::endl;
+ if (event.content.size() > 0)
+ os << indent << " content: '" << event.content << "'" << std::endl;
if (event.params.size() > 0) {
std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin();
os << indent << " params:" << std::endl;
diff --git a/src/uscxml/messages/Event.h b/src/uscxml/messages/Event.h
index 1acfce7..6697bb9 100644
--- a/src/uscxml/messages/Event.h
+++ b/src/uscxml/messages/Event.h
@@ -22,6 +22,56 @@
#include "uscxml/messages/Data.h"
+#define ERROR_EXECUTION(identifier, cause) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.execution"; \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_EXECUTION2(identifier, cause, node) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.execution"; \
+ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_COMMUNICATION(identifier, cause) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.communication"; \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_COMMUNICATION2(identifier, cause, node) \
+ uscxml::Event identifier; \
+ identifier.data.compound["cause"] = uscxml::Data(cause, uscxml::Data::VERBATIM); \
+ identifier.name = "error.communication"; \
+ identifier.data.compound["xpath"] = uscxml::Data(DOMUtils::xPathForNode(node), uscxml::Data::VERBATIM); \
+ identifier.eventType = uscxml::Event::PLATFORM;
+
+#define ERROR_EXECUTION_THROW(cause) \
+{\
+ ERROR_EXECUTION(exc, cause); \
+ throw exc;\
+}
+
+#define ERROR_EXECUTION_THROW2(cause, node) \
+{\
+ ERROR_EXECUTION2(exc, cause, node); \
+ throw exc;\
+}
+
+#define ERROR_COMMUNICATION_THROW(cause) \
+{\
+ ERROR_COMMUNICATION(exc, cause); \
+ throw exc;\
+}
+
+#define ERROR_COMMUNICATION_THROW2(cause, node) \
+{\
+ ERROR_COMMUNICATION(exc, cause, node); \
+ throw exc;\
+}
+
namespace uscxml {
class USCXML_API Event {
@@ -145,6 +195,13 @@ public:
return params;
}
+ void setNameList(const std::map<std::string, Data>& nameList) {
+ this->namelist = nameList;
+ }
+ void setParams(const std::multimap<std::string, Data>& params) {
+ this->params = params;
+ }
+
typedef std::multimap<std::string, Data> params_t;
typedef std::map<std::string, Data> namelist_t;
diff --git a/src/uscxml/messages/InvokeRequest.cpp b/src/uscxml/messages/InvokeRequest.cpp
index a39c8c6..26d40ce 100644
--- a/src/uscxml/messages/InvokeRequest.cpp
+++ b/src/uscxml/messages/InvokeRequest.cpp
@@ -60,6 +60,7 @@ std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq) {
if (invokeReq.src.size() > 0)
os<< indent << " src: " << invokeReq.src << std::endl;
+#if 0
if (invokeReq.namelist.size() > 0) {
os << indent << " namelist: " << std::endl;
InvokeRequest::namelist_t::const_iterator namelistIter = invokeReq.namelist.begin();
@@ -80,6 +81,7 @@ std::ostream& operator<< (std::ostream& os, const InvokeRequest& invokeReq) {
if (invokeReq.content.size() > 0)
os << indent << " content: " << invokeReq.content << std::endl;
+#endif
_dataIndentation++;
os << (Event)invokeReq;
diff --git a/src/uscxml/messages/SendRequest.cpp b/src/uscxml/messages/SendRequest.cpp
index a8fbe13..497182c 100644
--- a/src/uscxml/messages/SendRequest.cpp
+++ b/src/uscxml/messages/SendRequest.cpp
@@ -103,7 +103,7 @@ std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) {
if (sendReq.delayMs > 0)
os<< indent << " delay: " << sendReq.delayMs << std::endl;
-
+#if 0
if (sendReq.namelist.size() > 0) {
os << indent << " namelist: " << std::endl;
SendRequest::namelist_t::const_iterator namelistIter = sendReq.namelist.begin();
@@ -124,7 +124,7 @@ std::ostream& operator<< (std::ostream& os, const SendRequest& sendReq) {
if (sendReq.content.size() > 0)
os << indent << " content: " << sendReq.content << std::endl;
-
+#endif
_dataIndentation++;
os << (Event)sendReq;
_dataIndentation--;
diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h
index 57d4b14..f142a60 100644
--- a/src/uscxml/plugins/DataModel.h
+++ b/src/uscxml/plugins/DataModel.h
@@ -86,10 +86,6 @@ public:
return "";
}
- static void throwErrorExecution(const std::string& cause);
- static void throwErrorPlatform(const std::string& cause);
-
- // we need it public for various static functions
protected:
InterpreterImpl* _interpreter;
};
diff --git a/src/uscxml/plugins/EventHandler.h b/src/uscxml/plugins/EventHandler.h
index d30feb9..7b38575 100644
--- a/src/uscxml/plugins/EventHandler.h
+++ b/src/uscxml/plugins/EventHandler.h
@@ -62,9 +62,9 @@ public:
virtual void send(const SendRequest& req) = 0;
virtual void runOnMainThread() {};
- void returnEvent(Event& event);
+ void returnEvent(Event& event, bool external = false);
void returnErrorExecution(const std::string&);
- void returnErrorPlatform(const std::string&);
+ void returnErrorCommunication(const std::string&);
protected:
InterpreterImpl* _interpreter;
diff --git a/src/uscxml/plugins/Invoker.h b/src/uscxml/plugins/Invoker.h
index c967331..4a142e4 100644
--- a/src/uscxml/plugins/Invoker.h
+++ b/src/uscxml/plugins/Invoker.h
@@ -33,6 +33,7 @@ class USCXML_API InvokerImpl : public EventHandlerImpl {
public:
virtual ~InvokerImpl() {}
virtual void invoke(const InvokeRequest& req) = 0;
+ virtual void uninvoke() {}
virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter) = 0;
};
@@ -65,6 +66,10 @@ public:
_impl->invoke(req);
}
+ virtual void uninvoke() {
+ _impl->uninvoke();
+ }
+
protected:
boost::shared_ptr<InvokerImpl> _impl;
};
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index b2fce62..6dc8c26 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -452,12 +452,7 @@ uint32_t JSCDataModel::getLength(const std::string& expr) {
result = evalAsValue("(" + expr + ").length");
JSType type = JSValueGetType(_ctx, result);
if (type == kJSTypeNull || type == kJSTypeUndefined) {
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
-
- throw(exceptionEvent);
+ ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
}
JSValueRef exception = NULL;
@@ -549,20 +544,20 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
} else if (HAS_ATTR(assignElem, "location")) {
key = ATTR(assignElem, "location");
}
- if (key.length() == 0)
- throw Event("error.execution", Event::PLATFORM);
-
+ if (key.length() == 0) {
+ ERROR_EXECUTION_THROW("Assign element has neither id nor location");
+ }
// flags on attribute are ignored?
if (key.compare("_sessionid") == 0) // test 322
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _sessionId");
if (key.compare("_name") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _name");
if (key.compare("_ioprocessors") == 0) // test 326
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _ioprocessors");
if (key.compare("_invokers") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _invokers");
if (key.compare("_event") == 0)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign to _event");
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
@@ -666,13 +661,7 @@ void JSCDataModel::handleException(JSValueRef exception) {
JSStringRelease(exceptionStringRef);
std::string exceptionMsg(buffer);
- Event exceptionEvent;
- exceptionEvent.data.compound["exception"] = Data(exceptionMsg, Data::VERBATIM);
- exceptionEvent.name = "error.execution";
- exceptionEvent.eventType = Event::PLATFORM;
-
- throw(exceptionEvent);
-
+ ERROR_EXECUTION_THROW(exceptionMsg);
}
JSValueRef JSCDataModel::jsPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
index 98d2dda..45d7a5c 100644
--- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp
@@ -65,7 +65,10 @@ void NULLDataModel::setEvent(const Event& event) {
}
Data NULLDataModel::getStringAsData(const std::string& content) {
- Data data;
+ Data data = Data::fromJSON(content);
+ if (data.empty()) {
+ data = Data(content, Data::VERBATIM);
+ }
return data;
}
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
index ad0c42b..8f5e588 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
@@ -37,10 +37,7 @@ extern "C" {
}
#define RETHROW_PLEX_AS_EVENT \
catch (PlException plex) { \
- Event e; \
- e.name = "error.execution"; \
- e.data.compound["cause"] = (char*)plex; \
- throw e; \
+ ERROR_EXECUTION_THROW((char*)plex); \
} \
#define PL_MODULE \
@@ -733,10 +730,7 @@ std::string SWIDataModel::evalAsString(const std::string& expr) {
if (term.type() == PL_ATOM || term.type() == PL_CHARS || term.type() == PL_STRING) {
return std::string(term);
} else {
- Event e;
- e.name = "error.execution";
- e.data.compound["cause"] = (char*)plex;
- throw e;
+ ERROR_EXECUTION_THROW((char*)plex);
}
}
}
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
index 8bfc39d..4300512 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp
@@ -100,11 +100,11 @@ bool PromelaDataModel::validate(const std::string& location, const std::string&
uint32_t PromelaDataModel::getLength(const std::string& expr) {
if (!isDeclared(expr)) {
- throwErrorExecution("Variable " + expr + " was not declared");
+ ERROR_EXECUTION_THROW("Variable '" + expr + "' was not declared");
}
if (!_variables[expr].hasKey("size")) {
- throwErrorExecution("Variable " + expr + " is no array");
+ ERROR_EXECUTION_THROW("Variable '" + expr + "' is no array");
}
return strTo<int>(_variables[expr]["size"].atom);
@@ -216,7 +216,7 @@ void PromelaDataModel::evaluateDecl(void* ast) {
_variables.compound[name->value] = variable;
} else {
- throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
+ ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
}
}
assert(opIter == node->operands.end());
@@ -227,7 +227,7 @@ void PromelaDataModel::evaluateDecl(void* ast) {
evaluateDecl(*declIter);
}
} else {
- throwErrorExecution("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
+ ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
}
}
@@ -269,7 +269,7 @@ int PromelaDataModel::evaluateExpr(void* ast) {
case PML_OR:
return evaluateExpr(*opIter++) != 0 || evaluateExpr(*opIter++) != 0;
default:
- throwErrorExecution("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
+ ERROR_EXECUTION_THROW("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
}
return 0;
}
@@ -291,7 +291,7 @@ void PromelaDataModel::evaluateStmnt(void* ast) {
break;
}
default:
- throwErrorExecution("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
+ ERROR_EXECUTION_THROW("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
}
}
@@ -306,15 +306,15 @@ void PromelaDataModel::setVariable(void* ast, int value) {
int index = evaluateExpr(expr);
if (_variables.compound.find(name->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + name->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
}
if (!_variables[name->value].hasKey("size")) {
- throwErrorExecution("Variable " + name->value + " is no array");
+ ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
}
if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
- throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
}
_variables.compound[name->value].compound["value"][index] = Data(value, Data::VERBATIM);
@@ -339,10 +339,10 @@ int PromelaDataModel::getVariable(void* ast) {
switch(node->type) {
case PML_NAME:
if (_variables.compound.find(node->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + node->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + node->value + " was declared");
}
if (_variables[node->value].compound.find("size") != _variables[node->value].compound.end()) {
- throwErrorExecution("Type error: Variable " + node->value + " is an array");
+ ERROR_EXECUTION_THROW("Type error: Variable " + node->value + " is an array");
}
return strTo<int>(_variables[node->value]["value"].atom);
case PML_VAR_ARRAY: {
@@ -351,20 +351,20 @@ int PromelaDataModel::getVariable(void* ast) {
int index = evaluateExpr(expr);
if (_variables.compound.find(name->value) == _variables.compound.end()) {
- throwErrorExecution("No variable " + name->value + " was declared");
+ ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
}
if (!_variables[name->value].hasKey("size")) {
- throwErrorExecution("Variable " + name->value + " is no array");
+ ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
}
if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
- throwErrorExecution("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
+ ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
}
return strTo<int>(_variables.compound[name->value].compound["value"][index].atom);
}
default:
- throwErrorExecution("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
+ ERROR_EXECUTION_THROW("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
}
return 0;
}
diff --git a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
index cd3bbaf..d12b7fc 100644
--- a/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
+++ b/src/uscxml/plugins/datamodel/promela/PromelaParser.cpp
@@ -19,6 +19,7 @@
#include "PromelaParser.h"
#include "parser/promela.tab.hpp"
+#include "uscxml/messages/Event.h"
#include <iostream>
@@ -35,10 +36,7 @@ int promela_lex_destroy (void*);
void promela_error (uscxml::PromelaParser* ctx, void* yyscanner, const char* err) {
// mark as pending exception as we cannot throw from constructor and have the destructor called
- uscxml::Event excEvent;
- excEvent.data.compound["exception"] = uscxml::Data(err, uscxml::Data::VERBATIM);
- excEvent.name = "error.execution";
- excEvent.eventType = uscxml::Event::PLATFORM;
+ ERROR_EXECUTION(excEvent, err);
ctx->pendingException = excEvent;
}
@@ -53,12 +51,7 @@ PromelaParser::PromelaParser(const std::string& expr, Type expectedType) {
if (type != expectedType) {
std::stringstream ss;
ss << "Promela syntax type mismatch: Expected " << typeToDesc(expectedType) << " but got " << typeToDesc(type);
-
- uscxml::Event excEvent;
- excEvent.data.compound["exception"] = uscxml::Data(ss.str(), uscxml::Data::VERBATIM);
- excEvent.name = "error.execution";
- excEvent.eventType = uscxml::Event::PLATFORM;
- throw excEvent;
+ ERROR_EXECUTION_THROW(ss.str());
}
}
diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
index 4d9854b..5800f98 100644
--- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp
@@ -296,9 +296,7 @@ uint32_t XPathDataModel::getLength(const std::string& expr) {
return result.asNodeSet().size();
break;
default:
- Event exceptionEvent("error.execution", Event::PLATFORM);
- exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);
- throw(exceptionEvent);
+ ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
}
return 0;
}
@@ -326,7 +324,7 @@ void XPathDataModel::setForeach(const std::string& item,
if (!isDeclared(item)) {
if (!isValidIdentifier(item))
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Expression '" + item + "' not a valid identifier.");
Element<std::string> container = _doc.createElement("data");
container.setAttribute("id", item);
container.appendChild(arrayResult.asNodeSet()[iteration].cloneNode(true));
@@ -400,9 +398,9 @@ bool XPathDataModel::evalAsBool(const Arabica::DOM::Node<std::string>& node, con
try {
result = _xpath.evaluate_expr(expr, _doc);
} catch(SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
} catch(std::runtime_error e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
return result.asBool();
}
@@ -413,9 +411,9 @@ std::string XPathDataModel::evalAsString(const std::string& expr) {
try {
result = _xpath.evaluate_expr(expr, _doc);
} catch(SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
} catch(std::runtime_error e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
switch (result.type()) {
case STRING:
@@ -440,7 +438,7 @@ std::string XPathDataModel::evalAsString(const std::string& expr) {
break;
}
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY not supported to evaluate as string");
break;
}
return "undefined";
@@ -472,13 +470,13 @@ void XPathDataModel::assign(const Element<std::string>& assignElem,
for (int i = 0; i < key.asNodeSet().size(); i++) {
Node<std::string> node = key.asNodeSet()[i];
if (node == _varResolver.resolveVariable("", "_ioprocessors").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _ioProcessors");
if (node == _varResolver.resolveVariable("", "_sessionid").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _sessionid");
if (node == _varResolver.resolveVariable("", "_name").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _name");
if (node == _varResolver.resolveVariable("", "_event").asNodeSet()[0])
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Cannot assign _event");
}
} catch (Event e) {}
}
@@ -570,11 +568,11 @@ void XPathDataModel::init(const Element<std::string>& dataElem,
}
case Arabica::XPath::BOOL:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("expr evaluates to type ANY");
}
_datamodel.appendChild(container);
} catch (SyntaxException e) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW(e.what());
}
} else {
LOG(ERROR) << "data element has no content";
@@ -595,7 +593,7 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
switch (key.type()) {
case NODE_SET:
if (key.asNodeSet().size() == 0) {
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("key for assign is empty nodeset");
}
switch (value.type()) {
case STRING:
@@ -611,14 +609,14 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
assign(key.asNodeSet(), value.asNodeSet(), assignElem);
break;
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported");
}
break;
case STRING:
case Arabica::XPath::BOOL:
case NUMBER:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported")
break;
}
}
@@ -637,7 +635,7 @@ void XPathDataModel::assign(const XPathValue<std::string>& key,
case Arabica::XPath::BOOL:
case NUMBER:
case ANY:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Type ANY as key for assign not supported")
}
}
@@ -665,7 +663,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
// addattribute: Add an attribute with the name specified by 'attr'
// and value specified by 'expr' to the node specified by 'location'.
if (!HAS_ATTR(assignElem, "attr"))
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Assign element is missing 'attr'")
element.setAttribute(ATTR(assignElem, "attr"), value);
} else {
/// test 547
@@ -677,7 +675,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
break;
}
default:
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Unsupported node type with assign");
break;
}
}
@@ -709,7 +707,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key,
break;
default:
// std::cout << key[i].getNodeType() << std::endl;
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Unsupported node type for assign");
break;
}
}
@@ -740,7 +738,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
// node specified by 'location', keeping the same parent.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
for (int i = 0; i < value.size(); i++) {
Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true));
parent.insertBefore(importedNode, element);
@@ -750,7 +748,7 @@ void XPathDataModel::assign(const Element<std::string>& key,
// specified by 'location', keeping the same parent.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
for (int i = value.size(); i; i--) {
Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true));
Node<std::string> nextSibling = element.getNextSibling();
@@ -764,16 +762,16 @@ void XPathDataModel::assign(const Element<std::string>& key,
// replace: Replace the node specified by 'location' by the value specified by 'expr'.
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
if (value.size() != 1)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Value not singular");
Node<std::string> importedNode = (value[0].getOwnerDocument() == _doc ? value[0].cloneNode(true) : _doc.importNode(value[0], true));
parent.replaceChild(importedNode, element);
} else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "delete")) {
// delete: Delete the node specified by 'location'. ('expr' is ignored.).
Node<std::string> parent = element.getParentNode();
if (!parent)
- throw Event("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION_THROW("Node has no parent");
parent.removeChild(element);
} else {
// replacechildren: Replace all the children at 'location' with the value specified by 'expr'.
@@ -791,7 +789,7 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri,
const std::string& name) const {
std::map<std::string, NodeSet<std::string> >::const_iterator n = _variables.find(name);
if(n == _variables.end()) {
- throw Event("error.execution");
+ ERROR_EXECUTION_THROW("No varable named '" + name + "'");
}
#if VERBOSE
std::cout << std::endl << "Getting " << name << ":" << std::endl;
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 5ee7357..bd62467 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -157,7 +157,7 @@ bool BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) {
if (reqEvent.name.length() == 0)
reqEvent.name = "http." + req.data.compound.at("type").atom;
- returnEvent(reqEvent);
+ returnEvent(reqEvent, true);
evhttp_send_reply(req.evhttpReq, 200, "OK", NULL);
return true;
}
@@ -287,7 +287,7 @@ void BasicHTTPIOProcessor::downloadCompleted(const URL& url) {
Event event;
event.data = url;
event.name = "HTTP." + statusPrefix + "." + statusRest;
- returnEvent(event);
+// returnEvent(event);
}
_sendRequests.erase(reqIter);
return;
diff --git a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
index becc00a..00b47f4 100644
--- a/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/scxml/SCXMLIOProcessor.cpp
@@ -129,10 +129,10 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
boost::shared_ptr<InterpreterImpl> other = instances[sessionId].lock();
other->receive(reqCopy);
} else {
- LOG(ERROR) << "Can not send to scxml session " << sessionId << " - not known" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to scxml session " + sessionId + " - not known");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
+
}
} else if (iequals(reqCopy.target, "#_parent")) {
/**
@@ -143,8 +143,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
if (_interpreter->_parentQueue != NULL) {
_interpreter->_parentQueue->push(reqCopy);
} else {
- LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to parent, we were not invoked or no parent queue is set");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
}
@@ -167,8 +166,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
LOG(ERROR) << "Exception caught while sending event to invoker " << invokeId;
}
} else {
- LOG(ERROR) << "Can not send to invoked component '" << invokeId << "', no such invokeId" << std::endl;
- Event error("error.communication", Event::PLATFORM);
+ ERROR_COMMUNICATION(error, "Can not send to invoked component '" + invokeId + "', no such invokeId");
error.sendid = reqCopy.sendid;
_interpreter->receiveInternal(error);
}
@@ -177,8 +175,7 @@ void SCXMLIOProcessor::send(const SendRequest& req) {
if (target.isAbsolute()) {
BasicHTTPIOProcessor::send(reqCopy);
} else {
- LOG(ERROR) << "Not sure what to make of the target '" << reqCopy.target << "' - raising error" << std::endl;
- Event error("error.execution", Event::PLATFORM);
+ ERROR_EXECUTION(error, "Not sure what to make of the target '" + reqCopy.target + "' - raising error");
error.sendid = reqCopy.sendid;
// test 159 still fails
// _interpreter->receiveInternal(error);
diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp
index 3bce169..fea97d8 100644
--- a/src/uscxml/transform/ChartToFSM.cpp
+++ b/src/uscxml/transform/ChartToFSM.cpp
@@ -972,9 +972,7 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t
for (int i = 0; i < transitions.size(); i++) {
if (HAS_ATTR(transitions[i], "eventexpr")) {
- Event e("error.execution", Event::PLATFORM);
- e.data.compound["cause"] = "Cannot flatten document with eventexpr attributes";
- throw e;
+ ERROR_EXECUTION_THROW("Cannot flatten document with eventexpr attributes");
}
if (HAS_ATTR(transitions[i], "event")) {
foundWithEvent = true;