From eab5c12b2a1b9cfee94e8d0cbe41fb5d78594bb5 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Thu, 31 Jul 2014 13:31:14 +0200 Subject: More adhoc extensions for interpreters --- .../uscxml/tests/invoker/TestCustomInvoker.java | 92 ------------- .../tests/invoker/adhoc/TestAdhocInvoker.java | 86 +++++++++++++ .../tests/invoker/factory/TestCustomInvoker.java | 92 +++++++++++++ .../uscxml/tests/ioprocessor/TestCustomIOProc.java | 143 --------------------- .../tests/ioprocessor/adhoc/TestAdhocIOProc.java | 142 ++++++++++++++++++++ .../ioprocessor/adhoc/console/ConsoleFrame.java | 77 +++++++++++ .../ioprocessor/adhoc/console/ConsoleIOProc.java | 84 ++++++++++++ .../tests/ioprocessor/console/ConsoleFrame.java | 74 ----------- .../tests/ioprocessor/console/ConsoleIOProc.java | 84 ------------ .../ioprocessor/factory/TestCustomIOProc.java | 143 +++++++++++++++++++++ src/bindings/swig/uscxml_beautify.i | 4 + src/bindings/swig/uscxml_ignores.i | 1 + src/uscxml/Interpreter.cpp | 36 ++++-- src/uscxml/Interpreter.h | 15 ++- src/uscxml/plugins/EventHandler.h | 9 +- src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp | 7 +- src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h | 1 + 17 files changed, 683 insertions(+), 407 deletions(-) delete mode 100644 embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java create mode 100644 embedding/java/src/org/uscxml/tests/invoker/adhoc/TestAdhocInvoker.java create mode 100644 embedding/java/src/org/uscxml/tests/invoker/factory/TestCustomInvoker.java delete mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java create mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/TestAdhocIOProc.java create mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleFrame.java create mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleIOProc.java delete mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleFrame.java delete mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleIOProc.java create mode 100644 embedding/java/src/org/uscxml/tests/ioprocessor/factory/TestCustomIOProc.java diff --git a/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java b/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java deleted file mode 100644 index ecbff9b..0000000 --- a/embedding/java/src/org/uscxml/tests/invoker/TestCustomInvoker.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.uscxml.tests.invoker; - -import org.uscxml.Data; -import org.uscxml.Event; -import org.uscxml.Factory; -import org.uscxml.Interpreter; -import org.uscxml.InterpreterException; -import org.uscxml.InvokeRequest; -import org.uscxml.Invoker; -import org.uscxml.SendRequest; -import org.uscxml.StringList; - -public class TestCustomInvoker extends Invoker { - - @Override - public StringList getNames() { - StringList ss = new StringList(); - ss.add("java"); - return ss; - } - - @Override - public Data getDataModelVariables() { - Data data = new Data(); - return data; - } - - @Override - public void send(SendRequest req) { - System.out.println(req); - if ("foo".equals(req.getName())) - returnEvent(new Event("received2"), true); // enqueue an external event - } - - @Override - public void invoke(InvokeRequest req) { - System.out.println(req); - if ("Some string content".equals(req.getContent())) { - returnEvent(new Event("received1"), true); // enqueue an external event - } - } - - @Override - public void uninvoke() { - System.out.println("uninvoke"); - } - - @Override - public Invoker create(Interpreter interpreter) { - TestCustomInvoker invoker = new TestCustomInvoker(); - invoker.swigReleaseOwnership(); - return invoker; - } - - /** - * @param args - * @throws InterpreterException - */ - public static void main(String[] args) throws InterpreterException { - System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); - - TestCustomInvoker invoker = new TestCustomInvoker(); - // just register prototype at global factory - Factory.getInstance().registerInvoker(invoker); - - String xml = - "" + - " " + - " " + - " Some string content" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - ""; - - // parse and interpret - Interpreter interpreter = Interpreter.fromXML(xml); - interpreter.interpret(); - } - -} diff --git a/embedding/java/src/org/uscxml/tests/invoker/adhoc/TestAdhocInvoker.java b/embedding/java/src/org/uscxml/tests/invoker/adhoc/TestAdhocInvoker.java new file mode 100644 index 0000000..9092910 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/invoker/adhoc/TestAdhocInvoker.java @@ -0,0 +1,86 @@ +package org.uscxml.tests.invoker.adhoc; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; +import org.uscxml.InvokeRequest; +import org.uscxml.Invoker; +import org.uscxml.SendRequest; +import org.uscxml.StringList; + +public class TestAdhocInvoker extends Invoker { + + @Override + public StringList getNames() { + StringList ss = new StringList(); + ss.add("java"); + return ss; + } + + @Override + public Data getDataModelVariables() { + Data data = new Data(); + return data; + } + + @Override + public void send(SendRequest req) { + System.out.println(req); + if ("foo".equals(req.getName())) + returnEvent(new Event("received2"), true); // enqueue an external event + } + + @Override + public void invoke(InvokeRequest req) { + System.out.println(req); + if ("Some string content".equals(req.getContent())) { + returnEvent(new Event("received1"), true); // enqueue an external event + } + } + + @Override + public void uninvoke() { + System.out.println("uninvoke"); + } + + /** + * @param args + * @throws InterpreterException + */ + public static void main(String[] args) throws InterpreterException { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + + String xml = + "" + + " " + + " " + + " Some string content" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + TestAdhocInvoker javainvoker1 = new TestAdhocInvoker(); + TestAdhocInvoker javainvoker2 = new TestAdhocInvoker(); + + // parse and interpret + Interpreter interpreter = Interpreter.fromXML(xml); + interpreter.setInvoker("javainvoker1", javainvoker1); + interpreter.setInvoker("javainvoker2", javainvoker2); + interpreter.interpret(); + + } + +} diff --git a/embedding/java/src/org/uscxml/tests/invoker/factory/TestCustomInvoker.java b/embedding/java/src/org/uscxml/tests/invoker/factory/TestCustomInvoker.java new file mode 100644 index 0000000..c9cf6bc --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/invoker/factory/TestCustomInvoker.java @@ -0,0 +1,92 @@ +package org.uscxml.tests.invoker.factory; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Factory; +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; +import org.uscxml.InvokeRequest; +import org.uscxml.Invoker; +import org.uscxml.SendRequest; +import org.uscxml.StringList; + +public class TestCustomInvoker extends Invoker { + + @Override + public StringList getNames() { + StringList ss = new StringList(); + ss.add("java"); + return ss; + } + + @Override + public Data getDataModelVariables() { + Data data = new Data(); + return data; + } + + @Override + public void send(SendRequest req) { + System.out.println(req); + if ("foo".equals(req.getName())) + returnEvent(new Event("received2"), true); // enqueue an external event + } + + @Override + public void invoke(InvokeRequest req) { + System.out.println(req); + if ("Some string content".equals(req.getContent())) { + returnEvent(new Event("received1"), true); // enqueue an external event + } + } + + @Override + public void uninvoke() { + System.out.println("uninvoke"); + } + + @Override + public Invoker create(Interpreter interpreter) { + TestCustomInvoker invoker = new TestCustomInvoker(); + invoker.swigReleaseOwnership(); + return invoker; + } + + /** + * @param args + * @throws InterpreterException + */ + public static void main(String[] args) throws InterpreterException { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + + TestCustomInvoker invoker = new TestCustomInvoker(); + // just register prototype at global factory + Factory.getInstance().registerInvoker(invoker); + + String xml = + "" + + " " + + " " + + " Some string content" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + // parse and interpret + Interpreter interpreter = Interpreter.fromXML(xml); + interpreter.interpret(); + } + +} diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java deleted file mode 100644 index 8a72abe..0000000 --- a/embedding/java/src/org/uscxml/tests/ioprocessor/TestCustomIOProc.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.uscxml.tests.ioprocessor; - -import java.io.IOException; -import java.io.StringReader; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.uscxml.Data; -import org.uscxml.Event; -import org.uscxml.Factory; -import org.uscxml.IOProcessor; -import org.uscxml.Interpreter; -import org.uscxml.InterpreterException; -import org.uscxml.SendRequest; -import org.uscxml.StringList; -import org.w3c.dom.Document; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class TestCustomIOProc extends IOProcessor { - - public Interpreter interpreter; - - /** - * The types we will handle on a element - */ - @Override - public StringList getNames() { - StringList ss = new StringList(); - ss.add("java"); - return ss; - } - - /** - * Optional data we want to make available at - * _ioprocessors[this.getNames.front()] in the datamodel - */ - @Override - public Data getDataModelVariables() { - return new Data(); - } - - /** - * Send from the SCXML interpreter to this ioprocessor - */ - @Override - public void send(SendRequest req) { - System.out.println(req); - // send in s1.onentry - if ("This is some content!".equals(req.getContent())) { - returnEvent(new Event("received1")); - return; - } - // send in s2.onentry - if (req.getParams().containsKey("foo") - && "bar".equals(req.getParams().get("foo").get(0).getAtom())) { - returnEvent(new Event("received2")); - return; - } - // send in s3 - if (req.getXML().length() > 0) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory - .newInstance(); - Document doc = factory.newDocumentBuilder().parse( - new InputSource(new StringReader(req.getXML()))); - System.out.println("Root element :" - + doc.getDocumentElement().getNodeName()); - if ("this".equals(doc.getDocumentElement().getNodeName())) { - returnEvent(new Event("received3")); - return; - } - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - /** - * Create a new instance of this - */ - @Override - public IOProcessor create(Interpreter interpreter) { - TestCustomIOProc ioProc = new TestCustomIOProc(); - ioProc.interpreter = interpreter; - ioProc.swigReleaseOwnership(); - return ioProc; - } - - /** - * @param args - * @throws InterpreterException - */ - public static void main(String[] args) throws InterpreterException { - System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); - - TestCustomIOProc ioproc = new TestCustomIOProc(); - // just register prototype at global factory - Factory.getInstance().registerIOProcessor(ioproc); - - String xml = - "" + - " " + - " " + - " " + - " This is some content!" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - ""; - - // parse and interpret - Interpreter interpreter = Interpreter.fromXML(xml); - interpreter.interpret(); - } - -} diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/TestAdhocIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/TestAdhocIOProc.java new file mode 100644 index 0000000..fcb9688 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/TestAdhocIOProc.java @@ -0,0 +1,142 @@ +package org.uscxml.tests.ioprocessor.adhoc; + +import java.io.IOException; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Factory; +import org.uscxml.IOProcessor; +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; +import org.uscxml.SendRequest; +import org.uscxml.StringList; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class TestAdhocIOProc extends IOProcessor { + + public Interpreter interpreter; + + /** + * The types we will handle on a element + */ + @Override + public StringList getNames() { + StringList ss = new StringList(); + ss.add("java"); + return ss; + } + + /** + * Optional data we want to make available at + * _ioprocessors[this.getNames.front()] in the datamodel + */ + @Override + public Data getDataModelVariables() { + return new Data(); + } + + /** + * Send from the SCXML interpreter to this ioprocessor + */ + @Override + public void send(SendRequest req) { + System.out.println(req); + // send in s1.onentry + if ("This is some content!".equals(req.getContent())) { + returnEvent(new Event("received1")); + return; + } + // send in s2.onentry + if (req.getParams().containsKey("foo") + && "bar".equals(req.getParams().get("foo").get(0).getAtom())) { + returnEvent(new Event("received2")); + return; + } + // send in s3 + if (req.getXML().length() > 0) { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + Document doc = factory.newDocumentBuilder().parse( + new InputSource(new StringReader(req.getXML()))); + System.out.println("Root element :" + + doc.getDocumentElement().getNodeName()); + if ("this".equals(doc.getDocumentElement().getNodeName())) { + returnEvent(new Event("received3")); + return; + } + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + /** + * Create a new instance of this + */ + @Override + public IOProcessor create(Interpreter interpreter) { + TestAdhocIOProc ioProc = new TestAdhocIOProc(); + ioProc.interpreter = interpreter; + ioProc.swigReleaseOwnership(); + return ioProc; + } + + /** + * @param args + * @throws InterpreterException + */ + public static void main(String[] args) throws InterpreterException { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + + String xml = + "" + + " " + + " " + + " " + + " This is some content!" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + TestAdhocIOProc ioProc = new TestAdhocIOProc(); + + // parse and interpret + Interpreter interpreter = Interpreter.fromXML(xml); + interpreter.addIOProcessor(ioProc); + interpreter.interpret(); + } + +} diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleFrame.java b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleFrame.java new file mode 100644 index 0000000..0dbe528 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleFrame.java @@ -0,0 +1,77 @@ +package org.uscxml.tests.ioprocessor.adhoc.console; + +import java.awt.Frame; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; + +public class ConsoleFrame extends Frame { + private static final long serialVersionUID = 3682378173372160680L; + private ConsoleIOProc ioProc; + + public ConsoleFrame() throws InterpreterException { + super("Input Frame"); + JPanel p = new JPanel(); + JLabel label = new JLabel("Key Listener!"); + p.add(label); + add(p); + setSize(200, 100); + + // instantiate SCXML interpreter + final Interpreter interpreter = Interpreter.fromXML( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""); + + /** + * ConsoleIOProc will register as a keyboard listener and send events to the interpreter. + * + * This circumvents the factory and registers instances directly. You will have to promise + * that the ioProc instance exists for the complete lifetime of the interpreter, otherwise + * finalize() will call the C++ destructor and SegFaults will occur. + */ + ioProc = new ConsoleIOProc(this); + interpreter.addIOProcessor(ioProc); + + // Start the interpreter in a separate thread + Thread intrerpreterThread = new Thread(new Runnable() { + @Override + public void run() { + try { + interpreter.interpret(); + } catch (InterpreterException e) { + e.printStackTrace(); + } + } + }); + intrerpreterThread.start(); + + // show the user interface + setVisible(true); + } + + public static void main(String[] args) throws InterpreterException { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + ConsoleFrame frame = new ConsoleFrame(); + } +} diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleIOProc.java new file mode 100644 index 0000000..41d4702 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/ioprocessor/adhoc/console/ConsoleIOProc.java @@ -0,0 +1,84 @@ +package org.uscxml.tests.ioprocessor.adhoc.console; + +import java.awt.Frame; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.IOProcessor; +import org.uscxml.SendRequest; +import org.uscxml.StringList; + +public class ConsoleIOProc extends IOProcessor implements KeyListener { + + public ConsoleIOProc(Frame frame) { + super(); + frame.addKeyListener(this); + } + + /** IOProcessor */ + @Override + public StringList getNames() { + StringList ss = new StringList(); + ss.add("console"); + return ss; + } + + /** IOProcessor */ + @Override + public Data getDataModelVariables() { + // return anything for _ioprocessor['console'] + Data data = Data.fromJSON("{ foo: \"bar\", test: [1,2,3,4,5,6] }"); + return data; + } + + /** IOProcessor */ + @Override + public void send(SendRequest req) { + // interpreter wants to send something, just print on console + System.out.println(req); + } + + /** KeyListener */ + @Override + public void keyPressed(KeyEvent e) { + Event evt = new Event("key.pressed"); + evt.setData(keyEventToData(e)); + returnEvent(evt, true); + } + + /** KeyListener */ + @Override + public void keyReleased(KeyEvent e) { + Event evt = new Event("key.released"); + evt.setData(keyEventToData(e)); + returnEvent(evt, true); + } + + /** KeyListener */ + @Override + public void keyTyped(KeyEvent e) { + Event evt = new Event("key.typed"); + evt.setData(keyEventToData(e)); + returnEvent(evt, true); + } + + static Data keyEventToData(KeyEvent e) { + Data data = new Data(); + data.put("id", new Data(e.getID())); + data.put("keyChar", new Data(e.getKeyChar())); + data.put("keyLocation", new Data(e.getKeyLocation())); + data.put("modifiers", new Data(e.getModifiers())); + data.put("modifiersEx", new Data(e.getModifiersEx())); + data.put("when", new Data(e.getWhen())); + data.put("actionKey", new Data(e.isActionKey())); + data.put("altDown", new Data(e.isAltDown())); + data.put("altGraphDown", new Data(e.isAltGraphDown())); + data.put("ctrlDown", new Data(e.isControlDown())); + data.put("metaDown", new Data(e.isMetaDown())); + data.put("shiftDown", new Data(e.isShiftDown())); + + return data; + } +} \ No newline at end of file diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleFrame.java b/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleFrame.java deleted file mode 100644 index a88cce4..0000000 --- a/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleFrame.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.uscxml.tests.ioprocessor.console; - -import java.awt.Frame; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.uscxml.Factory; -import org.uscxml.Interpreter; -import org.uscxml.InterpreterException; - -public class ConsoleFrame extends Frame { - - private static final long serialVersionUID = 3682378173372160680L; - private ConsoleIOProc ioProc; - - public ConsoleFrame() throws InterpreterException { - super("Input Frame"); - JPanel p = new JPanel(); - JLabel label = new JLabel("Key Listener!"); - p.add(label); - add(p); - setSize(200, 100); - - final Interpreter interpreter = Interpreter.fromXML( - "" - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + ""); - - ioProc = new ConsoleIOProc(this); - interpreter.addIOProcessor(ioProc); - - Thread intrerpreterThread = new Thread(new Runnable() { - @Override - public void run() { - try { - interpreter.interpret(); - } catch (InterpreterException e) { - e.printStackTrace(); - } - } - }); - intrerpreterThread.start(); - - setVisible(true); - } - - public static void main(String[] args) throws InterpreterException { - System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); - ConsoleFrame frame = new ConsoleFrame(); - - } - -} - diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleIOProc.java deleted file mode 100644 index a95f6cb..0000000 --- a/embedding/java/src/org/uscxml/tests/ioprocessor/console/ConsoleIOProc.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.uscxml.tests.ioprocessor.console; - -import java.awt.Frame; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; - -import org.uscxml.Data; -import org.uscxml.Event; -import org.uscxml.IOProcessor; -import org.uscxml.SendRequest; -import org.uscxml.StringList; - -public class ConsoleIOProc extends IOProcessor implements KeyListener { - - public ConsoleIOProc(Frame frame) { - super(); - frame.addKeyListener(this); - } - - /** IOProcessor */ - @Override - public StringList getNames() { - StringList ss = new StringList(); - ss.add("console"); - return ss; - } - - /** IOProcessor */ - @Override - public Data getDataModelVariables() { - // return anything for _ioprocessor['console'] - Data data = Data.fromJSON("{ foo: \"bar\", test: [1,2,3,4,5,6] }"); - return data; - } - - /** IOProcessor */ - @Override - public void send(SendRequest req) { - // interpreter wants to send something, just print on console - System.out.println(req); - } - - /** KeyListener */ - @Override - public void keyPressed(KeyEvent e) { - Event evt = new Event("key.pressed"); - evt.setData(keyEventToData(e)); - returnEvent(evt, true); - } - - /** KeyListener */ - @Override - public void keyReleased(KeyEvent e) { - Event evt = new Event("key.released"); - evt.setData(keyEventToData(e)); - returnEvent(evt, true); - } - - /** KeyListener */ - @Override - public void keyTyped(KeyEvent e) { - Event evt = new Event("key.typed"); - evt.setData(keyEventToData(e)); - returnEvent(evt, true); - } - - static Data keyEventToData(KeyEvent e) { - Data data = new Data(); - data.put("id", new Data(e.getID())); - data.put("keyChar", new Data(e.getKeyChar())); - data.put("keyLocation", new Data(e.getKeyLocation())); - data.put("modifiers", new Data(e.getModifiers())); - data.put("modifiersEx", new Data(e.getModifiersEx())); - data.put("when", new Data(e.getWhen())); - data.put("actionKey", new Data(e.isActionKey())); - data.put("altDown", new Data(e.isAltDown())); - data.put("altGraphDown", new Data(e.isAltGraphDown())); - data.put("ctrlDown", new Data(e.isControlDown())); - data.put("metaDown", new Data(e.isMetaDown())); - data.put("shiftDown", new Data(e.isShiftDown())); - - return data; - } -} \ No newline at end of file diff --git a/embedding/java/src/org/uscxml/tests/ioprocessor/factory/TestCustomIOProc.java b/embedding/java/src/org/uscxml/tests/ioprocessor/factory/TestCustomIOProc.java new file mode 100644 index 0000000..c37cdb4 --- /dev/null +++ b/embedding/java/src/org/uscxml/tests/ioprocessor/factory/TestCustomIOProc.java @@ -0,0 +1,143 @@ +package org.uscxml.tests.ioprocessor.factory; + +import java.io.IOException; +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.uscxml.Data; +import org.uscxml.Event; +import org.uscxml.Factory; +import org.uscxml.IOProcessor; +import org.uscxml.Interpreter; +import org.uscxml.InterpreterException; +import org.uscxml.SendRequest; +import org.uscxml.StringList; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class TestCustomIOProc extends IOProcessor { + + public Interpreter interpreter; + + /** + * The types we will handle on a element + */ + @Override + public StringList getNames() { + StringList ss = new StringList(); + ss.add("java"); + return ss; + } + + /** + * Optional data we want to make available at + * _ioprocessors[this.getNames.front()] in the datamodel + */ + @Override + public Data getDataModelVariables() { + return new Data(); + } + + /** + * Send from the SCXML interpreter to this ioprocessor + */ + @Override + public void send(SendRequest req) { + System.out.println(req); + // send in s1.onentry + if ("This is some content!".equals(req.getContent())) { + returnEvent(new Event("received1")); + return; + } + // send in s2.onentry + if (req.getParams().containsKey("foo") + && "bar".equals(req.getParams().get("foo").get(0).getAtom())) { + returnEvent(new Event("received2")); + return; + } + // send in s3 + if (req.getXML().length() > 0) { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + Document doc = factory.newDocumentBuilder().parse( + new InputSource(new StringReader(req.getXML()))); + System.out.println("Root element :" + + doc.getDocumentElement().getNodeName()); + if ("this".equals(doc.getDocumentElement().getNodeName())) { + returnEvent(new Event("received3")); + return; + } + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + /** + * Create a new instance of this + */ + @Override + public IOProcessor create(Interpreter interpreter) { + TestCustomIOProc ioProc = new TestCustomIOProc(); + ioProc.interpreter = interpreter; + ioProc.swigReleaseOwnership(); + return ioProc; + } + + /** + * @param args + * @throws InterpreterException + */ + public static void main(String[] args) throws InterpreterException { + System.load("/Users/sradomski/Documents/TK/Code/uscxml/build/cli/lib/libuscxmlNativeJava64.jnilib"); + + TestCustomIOProc ioproc = new TestCustomIOProc(); + // just register prototype at global factory + Factory.getInstance().registerIOProcessor(ioproc); + + String xml = + "" + + " " + + " " + + " " + + " This is some content!" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + // parse and interpret + Interpreter interpreter = Interpreter.fromXML(xml); + interpreter.interpret(); + } + +} diff --git a/src/bindings/swig/uscxml_beautify.i b/src/bindings/swig/uscxml_beautify.i index 76f371e..4f3d246 100644 --- a/src/bindings/swig/uscxml_beautify.i +++ b/src/bindings/swig/uscxml_beautify.i @@ -67,6 +67,10 @@ void setDataModel(WrappedDataModel* dataModel) { self->setDataModel(boost::shared_ptr(dataModel)); } + + void setInvoker(const std::string invokeId, uscxml::WrappedInvoker* invoker) { + self->setInvoker(invokeId, boost::shared_ptr(invoker)); + } std::vector getBasicConfiguration() { Arabica::XPath::NodeSet nativeConfig = self->getBasicConfiguration(); diff --git a/src/bindings/swig/uscxml_ignores.i b/src/bindings/swig/uscxml_ignores.i index b6a0a3f..f7d3dad 100644 --- a/src/bindings/swig/uscxml_ignores.i +++ b/src/bindings/swig/uscxml_ignores.i @@ -47,6 +47,7 @@ %ignore uscxml::Interpreter::setCmdLineOptions(std::map); %ignore uscxml::Interpreter::setDataModel(const DataModel& dataModel); %ignore uscxml::Interpreter::addIOProcessor(IOProcessor ioProc); +%ignore uscxml::Interpreter::setInvoker(const std::string& invokeId, Invoker invoker); %ignore uscxml::Interpreter::getDocument; %ignore uscxml::Interpreter::getImpl; %ignore uscxml::Interpreter::runOnMainThread; diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 5fcc3f7..b8e4bfe 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -1385,19 +1385,29 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node& element) { invokeReq.type = "http://www.w3.org/TR/scxml/"; Invoker invoker; - try { - invoker = _factory->createInvoker(invokeReq.type, this); - } catch (Event e) { - receiveInternal(e); - } - if (invoker) { - tthread::lock_guard lock(_pluginMutex); + // is there such an invoker already? + if (_invokers.find(invokeReq.invokeid) != _invokers.end()) { + invoker = _invokers[invokeReq.invokeid]; + } else { try { + invoker = _factory->createInvoker(invokeReq.type, this); invoker.setInvokeId(invokeReq.invokeid); - invoker.setType(invokeReq.type); invoker.setInterpreter(this); - invoker.setElement(Element(element)); _invokers[invokeReq.invokeid] = invoker; + } catch (Event e) { + receiveInternal(e); + } + } + if (invoker) { + tthread::lock_guard lock(_pluginMutex); + try { + + if (!invoker.getElement()) + invoker.setElement(Element(element)); + + if (invoker.getType().size() == 0) + invoker.setType(invokeReq.type); + try { USCXML_MONITOR_CALLBACK3(beforeInvoking, Arabica::DOM::Element(element), invokeReq.invokeid); @@ -1453,7 +1463,13 @@ void InterpreterImpl::cancelInvoke(const Arabica::DOM::Node& elemen USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element(element), invokeId) _invokers[invokeId].uninvoke(); - _invokers.erase(invokeId); + + /** + * This should not be necessary. Most invokers have their "clean-up" code in their + * destructor and not their uninvoke method - we need to refactor them all! + */ + if (_dontDestructOnUninvoke.find(invokeId) == _dontDestructOnUninvoke.end()) + _invokers.erase(invokeId); USCXML_MONITOR_CALLBACK3(beforeUninvoking, Element(element), invokeId) diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 8a2b282..dc889e3 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -364,7 +364,7 @@ public: nameIter++; } } - + const std::map& getIOProcessors() { return _ioProcessors; } @@ -377,6 +377,13 @@ public: return _dataModel; } + void setInvoker(const std::string& invokeId, Invoker invoker) { + _dontDestructOnUninvoke.insert(invokeId); + _invokers[invokeId] = invoker; + _invokers[invokeId].setInterpreter(this); + _invokers[invokeId].setInvokeId(invokeId); + } + const std::map& getInvokers() { return _invokers; } @@ -466,7 +473,8 @@ protected: bool _isInitialized; bool _domIsSetup; bool _userSuppliedDataModel; - + std::set _dontDestructOnUninvoke; + bool _isStarted; bool _isRunning; @@ -657,6 +665,9 @@ public: return _impl->getIOProcessors(); } + void setInvoker(const std::string& invokeId, Invoker invoker) { + _impl->setInvoker(invokeId, invoker); + } const std::map& getInvokers() { return _impl->getInvokers(); } diff --git a/src/uscxml/plugins/EventHandler.h b/src/uscxml/plugins/EventHandler.h index 7b38575..4078cfe 100644 --- a/src/uscxml/plugins/EventHandler.h +++ b/src/uscxml/plugins/EventHandler.h @@ -49,7 +49,10 @@ public: void setType(const std::string& type) { _type = type; } - + std::string getType() { + return _type; + } + void setElement(const Arabica::DOM::Element& element) { _element = element; } @@ -101,9 +104,13 @@ public: void setInvokeId(const std::string& invokeId) { _impl->setInvokeId(invokeId); } + void setType(const std::string& type) { _impl->setType(type); } + std::string getType() { + return _impl->getType(); + } void setElement(const Arabica::DOM::Element& element) { _impl->setElement(element); diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp index f232e52..9506867 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.cpp @@ -40,12 +40,16 @@ USCXMLInvoker::USCXMLInvoker() : _cancelled(false) { USCXMLInvoker::~USCXMLInvoker() { +}; + +void USCXMLInvoker::uninvoke() { _cancelled = true; Event event; event.name = "unblock.and.die"; if (_invokedInterpreter) _invokedInterpreter.receive(event); -}; + +} boost::shared_ptr USCXMLInvoker::create(InterpreterImpl* interpreter) { boost::shared_ptr invoker = boost::shared_ptr(new USCXMLInvoker()); @@ -67,6 +71,7 @@ void USCXMLInvoker::cancel(const std::string sendId) { } void USCXMLInvoker::invoke(const InvokeRequest& req) { + _cancelled = false; if (req.src.length() > 0) { _invokedInterpreter = Interpreter::fromURI(req.src); } else if (req.dom) { diff --git a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h index 7d10bf1..f6aa77a 100644 --- a/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h +++ b/src/uscxml/plugins/invoker/scxml/USCXMLInvoker.h @@ -60,6 +60,7 @@ public: virtual void send(const SendRequest& req); virtual void cancel(const std::string sendId); virtual void invoke(const InvokeRequest& req); + virtual void uninvoke(); protected: bool _cancelled; -- cgit v0.12