Modified: jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java (original) +++ jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/io/SCXMLDigesterTest.java Wed May 17 18:16:30 2006 @@ -25,7 +25,6 @@ import org.apache.commons.digester.Digester; import org.apache.commons.scxml.SCXMLTestHelper; -import org.apache.commons.scxml.model.Hello; import org.apache.commons.scxml.model.SCXML; import org.apache.commons.scxml.model.Send; import org.apache.commons.scxml.model.State; @@ -66,7 +65,7 @@ getResource("org/apache/commons/scxml/transitions-01.xml"); send01 = this.getClass().getClassLoader(). getResource("org/apache/commons/scxml/send-01.xml"); - digester = SCXMLDigester.newInstance(null, null); + digester = SCXMLDigester.newInstance(); } /** @@ -118,65 +117,6 @@ + " an example.</prompt></foo>"; assertFalse(scxmlAsString.indexOf(expectedFoo2Serialization) == -1); */ - } - - public void testAddGoodCustomAction01() { - try { - SCXMLDigester.addCustomAction(digester, - "http://my.actions.domain/CUSTOM", "hello", Hello.class); - } catch (IllegalArgumentException iae) { - fail("Failed to add custom action "Hello""); - } - } - - public void testAddBadCustomAction01() { - try { - SCXMLDigester.addCustomAction(digester, - null, "hello", Hello.class); - fail("Added custom action with illegal namespace"); - } catch (IllegalArgumentException iae) { - // Expected - } - } - - public void testAddBadCustomAction02() { - try { - SCXMLDigester.addCustomAction(digester, - " ", "hello", Hello.class); - fail("Added custom action with illegal namespace"); - } catch (IllegalArgumentException iae) { - // Expected - } - } - - public void testAddBadCustomAction03() { - try { - SCXMLDigester.addCustomAction(digester, - "http://my.actions.domain/CUSTOM", "", Hello.class); - fail("Added custom action with illegal local name"); - } catch (IllegalArgumentException iae) { - // Expected - } - } - - public void testAddBadCustomAction04() { - try { - SCXMLDigester.addCustomAction(digester, - "http://my.actions.domain/CUSTOM", " ", Hello.class); - fail("Added custom action with illegal local name"); - } catch (IllegalArgumentException iae) { - // Expected - } - } - - public void testAddBadCustomAction05() { - try { - SCXMLDigester.addCustomAction(digester, - "http://my.actions.domain/CUSTOM", "foo", this.getClass()); - fail("Added custom action which is not an Action class subtype"); - } catch (IllegalArgumentException iae) { - // Expected - } } private String serialize(final SCXML scxml) {
Modified: jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/CustomActionTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/CustomActionTest.java?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/CustomActionTest.java (original) +++ jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/CustomActionTest.java Wed May 17 18:16:30 2006 @@ -16,6 +16,8 @@ package org.apache.commons.scxml.model; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import junit.framework.Test; import junit.framework.TestCase; @@ -24,9 +26,6 @@ import org.apache.commons.digester.Digester; import org.apache.commons.scxml.SCXMLExecutor; import org.apache.commons.scxml.SCXMLTestHelper; -import org.apache.commons.scxml.io.SCXMLDigester; -import org.apache.commons.scxml.model.SCXML; -import org.apache.commons.scxml.model.State; public class CustomActionTest extends TestCase { @@ -43,7 +42,7 @@ junit.textui.TestRunner.main(testCaseName); } - private URL hello01, custom01; + private URL hello01, custom01, external01; private Digester digester; private SCXMLExecutor exec; @@ -54,18 +53,77 @@ hello01 = this.getClass().getClassLoader(). getResource("org/apache/commons/scxml/hello-world.xml"); custom01 = this.getClass().getClassLoader(). - getResource("org/apache/commons/scxml/custom-hello-world.xml"); + getResource("org/apache/commons/scxml/custom-hello-world-01.xml"); + external01 = this.getClass().getClassLoader(). + getResource("org/apache/commons/scxml/external-hello-world.xml"); } /** * Tear down instance variables required by this test case. */ public void tearDown() { - hello01 = custom01 = null; + hello01 = custom01 = external01 = null; digester = null; exec = null; } + public void testAddGoodCustomAction01() { + try { + new CustomAction("http://my.actions.domain/CUSTOM", "hello", + Hello.class); + } catch (IllegalArgumentException iae) { + fail("Failed to add custom action "Hello""); + } + } + + public void testAddBadCustomAction01() { + try { + new CustomAction(null, "hello", Hello.class); + fail("Added custom action with illegal namespace"); + } catch (IllegalArgumentException iae) { + // Expected + } + } + + public void testAddBadCustomAction02() { + try { + new CustomAction(" ", "hello", Hello.class); + fail("Added custom action with illegal namespace"); + } catch (IllegalArgumentException iae) { + // Expected + } + } + + public void testAddBadCustomAction03() { + try { + new CustomAction("http://my.actions.domain/CUSTOM", "", + Hello.class); + fail("Added custom action with illegal local name"); + } catch (IllegalArgumentException iae) { + // Expected + } + } + + public void testAddBadCustomAction04() { + try { + new CustomAction("http://my.actions.domain/CUSTOM", " ", + Hello.class); + fail("Added custom action with illegal local name"); + } catch (IllegalArgumentException iae) { + // Expected + } + } + + public void testAddBadCustomAction05() { + try { + new CustomAction("http://my.actions.domain/CUSTOM", "foo", + this.getClass()); + fail("Added custom action which is not an Action class subtype"); + } catch (IllegalArgumentException iae) { + // Expected + } + } + // Hello World example using the SCXML <log> action public void testHelloWorld() { // (1) Get a SCXMLExecutor @@ -78,26 +136,52 @@ // Hello World example using a custom <hello> action public void testCustomActionHelloWorld() { - // (1) Get Digester with "default" rules for parsing SCXML documents - digester = SCXMLDigester.newInstance(null, null); - // (2) Register the "custom" action(s) - SCXMLDigester.addCustomAction(digester, - "http://my.custom-actions.domain/CUSTOM", "hello", Hello.class); - // (3) Parse the SCXML document containing the custom action(s) - SCXML scxml = null; - try { - scxml = (SCXML) digester.parse(custom01.toString()); - } catch (Exception e) { - fail(e.getMessage()); - } - // (4) Wire up the object model for the SCXMLExecutor - SCXMLDigester.updateSCXML(scxml); - // (5) Get a SCXMLExecutor + // (1) Form a list of custom actions defined in the SCXML + // document (and any included documents via "src" attributes) + CustomAction ca1 = + new CustomAction("http://my.custom-actions.domain/CUSTOM1", + "hello", Hello.class); + // Register the same action under a different name, just to test + // multiple custom actions + CustomAction ca2 = + new CustomAction("http://my.custom-actions.domain/CUSTOM2", + "bar", Hello.class); + List customActions = new ArrayList(); + customActions.add(ca1); + customActions.add(ca2); + // (2) Parse the document with a custom digester. + SCXML scxml = SCXMLTestHelper.digest(custom01, customActions); + // (3) Get a SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml); - // (6) Fire events, proceed as usual + // (4) Single, final state assertEquals("custom", ((State) exec.getCurrentStatus().getStates(). iterator().next()).getId()); assertTrue(exec.getCurrentStatus().isFinal()); + } + + // Hello World example using custom <my:hello> action + // as part of an external state source (src attribute) + public void testCustomActionExternalSrcHelloWorld() { + // (1) Form a list of custom actions defined in the SCXML + // document (and any included documents via "src" attributes) + CustomAction ca = + new CustomAction("http://my.custom-actions.domain/CUSTOM", + "hello", Hello.class); + List customActions = new ArrayList(); + customActions.add(ca); + // (2) Parse the document with a custom digester. + SCXML scxml = SCXMLTestHelper.digest(external01, customActions); + // (3) Get a SCXMLExecutor + exec = SCXMLTestHelper.getExecutor(scxml); + // (4) Single, final state + assertEquals("custom", ((State) exec.getCurrentStatus().getStates(). + iterator().next()).getId()); + } + + // The custom action defined by Hello.class should be called + // to execute() exactly 4 times upto this point + public void testCustomActionCallbacks() { + assertEquals(4, Hello.callbacks); } } Modified: jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/Hello.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/Hello.java?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/Hello.java (original) +++ jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/Hello.java Wed May 17 18:16:30 2006 @@ -31,6 +31,8 @@ /** This is who we say hello to. */ private String name; + /** We count callbacks to execute() as part of the test suite. */ + public static int callbacks = 0; /** Public constructor is needed for the I in SCXML IO. */ public Hello() { @@ -65,6 +67,7 @@ if (appLog.isInfoEnabled()) { appLog.info("Hello " + name); } + callbacks++; } } Modified: jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/HistoryTest.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/HistoryTest.java?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/HistoryTest.java (original) +++ jakarta/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/model/HistoryTest.java Wed May 17 18:16:30 2006 @@ -15,12 +15,21 @@ */ package org.apache.commons.scxml.model; +import java.net.URL; +import java.util.Set; + import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -public class HistoryTest extends TestCase { +import org.apache.commons.scxml.SCXMLExecutor; +import org.apache.commons.scxml.SCXMLTestHelper; +public class HistoryTest extends TestCase { + /** + * Construct a new instance of HistoryTest with + * the specified name + */ public HistoryTest(String testName) { super(testName); } @@ -33,13 +42,37 @@ String[] testCaseName = { HistoryTest.class.getName()}; junit.textui.TestRunner.main(testCaseName); } - + + // Test data private History history; - + private URL shallow01, deep01, defaults01; + private SCXMLExecutor exec; + + /** + * Set up instance variables required by this test case. + */ public void setUp() { history = new History(); + shallow01 = this.getClass().getClassLoader(). + getResource("org/apache/commons/scxml/history-shallow-01.xml"); + deep01 = this.getClass().getClassLoader(). + getResource("org/apache/commons/scxml/history-deep-01.xml"); + defaults01 = this.getClass().getClassLoader(). + getResource("org/apache/commons/scxml/history-default-01.xml"); } - + + /** + * Tear down instance variables required by this test case. + */ + public void tearDown() { + history = null; + shallow01 = deep01 = defaults01 = null; + exec = null; + } + + /** + * Test the implementation + */ public void testSetTypeDeep() { history.setType("deep"); @@ -51,4 +84,70 @@ assertFalse(history.isDeep()); } + + public void testShallowHistory01() { + exec = SCXMLTestHelper.getExecutor(shallow01); + runHistoryFlow(); + } + + public void testDeepHistory01() { + exec = SCXMLTestHelper.getExecutor(deep01); + runHistoryFlow(); + } + + public void testHistoryDefaults01() { + exec = SCXMLTestHelper.getExecutor(defaults01); + Set currentStates = exec.getCurrentStatus().getStates(); + assertEquals(1, currentStates.size()); + assertEquals("state11", ((State)currentStates.iterator(). + next()).getId()); + currentStates = SCXMLTestHelper.fireEvent(exec, "state.next"); + assertEquals(1, currentStates.size()); + assertEquals("state211", ((State)currentStates.iterator(). + next()).getId()); + currentStates = SCXMLTestHelper.fireEvent(exec, "state.next"); + assertEquals(1, currentStates.size()); + assertEquals("state31", ((State)currentStates.iterator(). + next()).getId()); + } + + private void runHistoryFlow() { + Set currentStates = exec.getCurrentStatus().getStates(); + assertEquals(1, currentStates.size()); + assertEquals("phase1", ((State)currentStates.iterator(). + next()).getId()); + assertEquals("phase1", pauseAndResume()); + assertEquals("phase2", nextPhase()); + // pause and resume couple of times for good measure + assertEquals("phase2", pauseAndResume()); + assertEquals("phase2", pauseAndResume()); + assertEquals("phase3", nextPhase()); + assertEquals("phase3", pauseAndResume()); + try { + exec.reset(); + } catch (ModelException me) { + fail(me.getMessage()); + } + currentStates = exec.getCurrentStatus().getStates(); + assertEquals(1, currentStates.size()); + assertEquals("phase1", ((State)currentStates.iterator(). + next()).getId()); + } + + private String pauseAndResume() { + Set currentStates = SCXMLTestHelper.fireEvent(exec, "flow.pause"); + assertEquals(1, currentStates.size()); + assertEquals("interrupted", ((State)currentStates.iterator(). + next()).getId()); + currentStates = SCXMLTestHelper.fireEvent(exec, "flow.resume"); + assertEquals(1, currentStates.size()); + return ((State)currentStates.iterator().next()).getId(); + } + + private String nextPhase() { + Set currentStates = SCXMLTestHelper.fireEvent(exec, "phase.done"); + assertEquals(1, currentStates.size()); + return ((State)currentStates.iterator().next()).getId(); + } + } Modified: jakarta/commons/proper/scxml/trunk/xdocs/guide/core-digester.xml URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/xdocs/guide/core-digester.xml?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/xdocs/guide/core-digester.xml (original) +++ jakarta/commons/proper/scxml/trunk/xdocs/guide/core-digester.xml Wed May 17 18:16:30 2006 @@ -38,6 +38,7 @@ //import java.io.IOException; //import java.net.URL; //import org.apache.commons.scxml.io.SCXMLDigester; + //import org.apache.commons.scxml.model.ModelException; //import org.apache.commons.scxml.model.SCXML; //import org.xml.sax.ErrorHandler; //import org.xml.sax.SAXException; @@ -50,6 +51,8 @@ // IOException while parsing } catch (SAXException se) { // SAXException while parsing + } catch (ModelException me) { + // ModelException while parsing } Modified: jakarta/commons/proper/scxml/trunk/xdocs/guide/custom-actions.xml URL: http://svn.apache.org/viewvc/jakarta/commons/proper/scxml/trunk/xdocs/guide/custom-actions.xml?rev=407424&r1=407423&r2=407424&view=diff ============================================================================== --- jakarta/commons/proper/scxml/trunk/xdocs/guide/custom-actions.xml (original) +++ jakarta/commons/proper/scxml/trunk/xdocs/guide/custom-actions.xml Wed May 17 18:16:30 2006 @@ -118,28 +118,41 @@ </subsection> - <subsection name="Registering the action with the digester"> + <subsection name="Using a custom SCXML digester"> - <p>With the custom action implemented, obtain a configured digester which - has the "default" ruleset required for reading (parsing) SCXML - documents, and then register the custom action like so:</p> + <p>With the custom action(s) implemented, the document may be + parsed using a custom SCXML digester that is aware of these actions + like so:</p> <pre> - // (1) Get Digester with "default" rules for parsing SCXML documents - Digester digester = SCXMLDigester.newInstance(null, null); + // (1) Create a list of custom actions, add as many as are needed + List customActions = new ArrayList(); + CustomAction ca = + new CustomAction("http://my.custom-actions.domain/CUSTOM", + "hello", Hello.class); + customActions.add(ca); - // (2) Register the "custom" action(s) - SCXMLDigester.addCustomAction(digester, - "http://my.custom-actions.domain/CUSTOM", "hello", Hello.class); + // (2) Parse the SCXML document containing the custom action(s) + SCXML scxml = null; + try { + scxml = SCXMLDigester.digest(url, errorHandler, customActions); + // Also see other methods in SCXMLDigester API + // "url" points to SCXML document + // "errorHandler" is SAX ErrorHandler + } catch (Exception e) { + // bad document, take necessary action + } </pre> - <p>This static addCustomAction() method can only be used if the custom + <p>This approach can only be used if the custom rule has no body content (child "tags") or if the custom action implements the <a href="../apidocs/org/apache/commons/scxml/model/ExternalContent.html">ExternalContent</a> interface, in which case, any body content gets read into a list of DOM nodes. For any other requirements, the digester rules - can be added by directly using the + can be added by directly by obtaining a Digester instance with the + "default" SCXML rules using the <code>newInstance()</code> methods + and further directly adding the necessary rules using the <a href="http://jakarta.apache.org/commons/digester/commons-digester-1.7/docs/api/">digester API</a> .</p> @@ -147,24 +160,6 @@ <subsection name="Read in the 'custom' SCXML document"> - <p>This involves parsing the document and making the resulting - SCXML object executor-ready (which allows us to detect any - "model inconsistencies" before feeding it to the - execution engine). That amounts to:</p> - - <pre> - // (3) Parse the SCXML document containing the custom action(s) - SCXML scxml = null; - try { - scxml = (SCXML) digester.parse(<String>); - //String method as an example - } catch (Exception e) { - // bad document, take necessary action - } - // (4) Wire up the object model for the SCXMLExecutor - SCXMLDigester.updateSCXML(scxml); - </pre> - <p>For documents without custom actions, the utility methods of the <a href="../apidocs/org/apache/commons/scxml/io/SCXMLDigester.html">SCXMLDigester</a> should be used. That section is @@ -175,7 +170,7 @@ <subsection name="Launching the engine"> - <p>Having obtained the SCXML object beyond step (4) above, + <p>Having obtained the SCXML object beyond step (2) above, proceed as usual, see the section on the <a href="core-engine.html">Commons SCXML engine</a> for details.</p> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
