You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-dev@jakarta.apache.org by ra...@apache.org on 2005/08/10 23:11:40 UTC
svn commit: r231329 [10/13] - in /jakarta/taglibs/proper/rdc/trunk/src:
META-INF/tags/rdc/ org/apache/taglibs/rdc/ org/apache/taglibs/rdc/core/
org/apache/taglibs/rdc/dm/ org/apache/taglibs/rdc/resources/
org/apache/taglibs/rdc/sampleapps/mortgage/ org...
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLDigester.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLDigester.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLDigester.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLDigester.java Wed Aug 10 14:10:59 2005
@@ -67,842 +67,842 @@
*/
public class SCXMLDigester {
- private static final String ERR_PARSE_FAIL = "<!-- Error parsing " +
- "SCXML document for group: \"{0}\", with message: \"{1}\" -->\n";
+ private static final String ERR_PARSE_FAIL = "<!-- Error parsing " +
+ "SCXML document for group: \"{0}\", with message: \"{1}\" -->\n";
- // Logging
- private static org.apache.commons.logging.Log log = LogFactory
- .getLog(SCXMLDigester.class);
-
- //-- PUBLIC METHODS --//
- /**
- * API for standalone usage where the SCXML document is a URL.
- *
- * @param scxmlURL
- * a canonical absolute URL to parse (relative URLs within the
- * top level document are to be resovled against this URL).
- * @param errHandler
- * The SAX ErrorHandler
- * @param evalCtx
- * the document-level variable context for guard condition
- * evaluation
- * @param evalEngine
- * the scripting/expression language engine for creating local
- * state-level variable contexts (if supported by a given
- * scripting engine)
- *
- * @return SCXML The SCXML object corresponding to the file argument
- *
- * @see Context
- * @see ErrorHandler
- * @see Evaluator
- * @see PathResolver
- */
- public static SCXML digest(URL scxmlURL, ErrorHandler errHandler,
- Context evalCtx, Evaluator evalEngine) {
-
- SCXML scxml = null;
- Digester scxmlDigester = SCXMLDigester
- .newInstance(null, new URLResolver(scxmlURL));
- scxmlDigester.setErrorHandler(errHandler);
-
- try {
- scxml = (SCXML) scxmlDigester.parse(scxmlURL.toString());
- } catch (Exception e) {
- MessageFormat msgFormat = new MessageFormat(ERR_PARSE_FAIL);
- String errMsg = msgFormat.format(new Object[] {scxmlURL.toString(),
- e.getMessage()});
- log.error(errMsg, e);
- }
-
- if (scxml != null) {
- updateSCXML(scxml, evalCtx, evalEngine);
- }
-
- return scxml;
-
- }
-
- /**
- * API for standalone usage where the SCXML document is a URI.
- * A PathResolver must be provided.
- *
- * @param pathResolver
- * The PathResolver for this context
- * @param documentRealPath
- * The String pointing to the absolute (real) path of the
- * SCXML config
- * @param errHandler
- * The SAX ErrorHandler
- * @param evalCtx
- * the document-level variable context for guard condition
- * evaluation
- * @param evalEngine
- * the scripting/expression language engine for creating local
- * state-level variable contexts (if supported by a given
- * scripting engine)
- *
- * @return SCXML The SCXML object corresponding to the file argument
- *
- * @see Context
- * @see ErrorHandler
- * @see Evaluator
- * @see PathResolver
- */
- public static SCXML digest(String documentRealPath,
- ErrorHandler errHandler, Context evalCtx, Evaluator evalEngine,
- PathResolver pr) {
-
- SCXML scxml = null;
- Digester scxmlDigester = SCXMLDigester.newInstance(null, pr);
- scxmlDigester.setErrorHandler(errHandler);
-
- try {
- scxml = (SCXML) scxmlDigester.parse(documentRealPath);
- } catch (Exception e) {
- MessageFormat msgFormat = new MessageFormat(ERR_PARSE_FAIL);
- String errMsg = msgFormat.format(new Object[] { documentRealPath,
- e.getMessage()});
- log.error(errMsg, e);
- }
-
- if (scxml != null) {
- updateSCXML(scxml, evalCtx, evalEngine);
- }
-
- return scxml;
-
- }
-
- /**
- * Serialize this SCXML object (primarily for debugging)
- *
- * @param scxml
- * The SCXML to be serialized
- * @return String The serialized SCXML
- */
- public static String serializeSCXML(SCXML scxml) {
- StringBuffer b = new StringBuffer("<scxml xmlns=\"").append(
- scxml.getXmlns()).append("\" version=\"").append(
- scxml.getVersion()).append("\" initialstate=\"").append(
- scxml.getInitialstate()).append("\">\n");
- Map s = scxml.getStates();
- Iterator i = s.keySet().iterator();
- while (i.hasNext()) {
- serializeState(b, (State) s.get(i.next()), INDENT);
- }
- b.append("</scxml>\n");
- return b.toString();
- }
-
- //-- PRIVATE CONSTANTS --//
- //// Patterns to get the digestion going
- private static final String XP_SM = "scxml";
-
- private static final String XP_SM_ST = "scxml/state";
-
- //// Universal matches
- // State
- private static final String XP_ST_ST = "!*/state/state";
-
- private static final String XP_PAR_ST = "!*/parallel/state";
-
- private static final String XP_TR_TAR_ST = "!*/transition/target/state";
-
- //private static final String XP_ST_TAR_ST = "!*/state/target/state";
-
- // Parallel
- private static final String XP_ST_PAR = "!*/state/parallel";
-
- // If
- private static final String XP_IF = "!*/if";
-
- //// Path Fragments
- // Onentries and Onexits
- private static final String XP_ONEN = "/onentry";
-
- private static final String XP_ONEX = "/onexit";
-
- // Initial
- private static final String XP_INI = "/initial";
-
- // History
- private static final String XP_HIST = "/history";
-
- // Transition, target and exit
- private static final String XP_TR = "/transition";
-
- private static final String XP_TAR = "/target";
-
- private static final String XP_ST = "/state";
-
- private static final String XP_EXT = "/exit";
-
- // Actions
- private static final String XP_VAR = "/var";
-
- private static final String XP_ASN = "/assign";
-
- private static final String XP_LOG = "/log";
-
- private static final String XP_SND = "/send";
-
- private static final String XP_CAN = "/cancel";
-
- private static final String XP_EIF = "/elseif";
-
- private static final String XP_ELS = "/else";
-
- //// Other constants
- private static final String INDENT = " ";
-
- //-- PRIVATE UTILITY METHODS --//
- /*
- * Get a SCXML digester instance
- *
- * @return Digester A newly configured SCXML digester instance
- */
- private static Digester newInstance(SCXML scxml, PathResolver sc) {
-
- Digester digester = new Digester();
- //Uncomment next line after SCXML DTD is available
- //digester.setValidating(true);
- digester.setRules(initRules(scxml, sc));
- return digester;
- }
-
- /*
- * Private utility functions for configuring digester rule base for SCXML
- */
- private static ExtendedBaseRules initRules(SCXML scxml, PathResolver sc) {
-
- ExtendedBaseRules scxmlRules = new ExtendedBaseRules();
-
- //// SCXML
- scxmlRules.add(XP_SM, new ObjectCreateRule(SCXML.class));
- scxmlRules.add(XP_SM, new SetPropertiesRule());
-
- //// States
- // Level one states
- addStateRules(XP_SM_ST, scxmlRules, scxml, sc, 0);
- scxmlRules.add(XP_SM_ST, new SetNextRule("addState"));
- // Nested states
- addStateRules(XP_ST_ST, scxmlRules, scxml, sc, 1);
- scxmlRules.add(XP_ST_ST, new SetNextRule("addChild"));
- // Initial states (no longer needed due to addition of Initial)
- //addStateRules(XP_ST_TAR_ST, scxmlRules, scxml, sc, 1);
- //scxmlRules.add(XP_ST_TAR_ST, new SetNextRule("addChild"));
- //scxmlRules.add(XP_ST_TAR_ST, new SetNextRule("setInitial"));
- // Parallel states
- addStateRules(XP_PAR_ST, scxmlRules, scxml, sc, 1);
- scxmlRules.add(XP_PAR_ST, new SetNextRule("addState"));
- // Target states
- addStateRules(XP_TR_TAR_ST, scxmlRules, scxml, sc, 2);
- scxmlRules.add(XP_TR_TAR_ST, new SetNextRule("setTarget"));
-
- //// Parallels
- addParallelRules(XP_ST_PAR, scxmlRules, scxml);
-
- //// Ifs
- addIfRules(XP_IF, scxmlRules);
-
- return scxmlRules;
-
- }
-
- private static void addStateRules(String xp, ExtendedBaseRules scxmlRules,
- SCXML scxml, PathResolver sc, int parent) {
- scxmlRules.add(xp, new ObjectCreateRule(State.class));
- addStatePropertiesRules(xp, scxmlRules, sc);
- //scxmlRules.add(xp + XP_TAR, new SetPropertiesRule());
- //scxmlRules.add(xp + XP_INI_TR_TAR, new SetPropertiesRule());
- addInitialRule(xp + XP_INI, scxmlRules, sc, scxml);
- addHistoryRules(xp + XP_HIST, scxmlRules, sc, scxml);
- addParentRule(xp, scxmlRules, parent);
- addTransitionRules(xp + XP_TR, scxmlRules, "addTransition");
- addHandlerRules(xp, scxmlRules);
- scxmlRules.add(xp, new UpdateModelRule(scxml));
- }
-
- private static void addParallelRules(String xp,
- ExtendedBaseRules scxmlRules, SCXML scxml) {
- addSimpleRulesTuple(xp, scxmlRules, Parallel.class, null, null,
- "setParallel");
- addHandlerRules(xp, scxmlRules);
- addParentRule(xp, scxmlRules, 1);
- scxmlRules.add(xp, new UpdateModelRule(scxml));
- }
-
- private static void addStatePropertiesRules(String xp,
- ExtendedBaseRules scxmlRules, PathResolver sc) {
- scxmlRules.add(xp, new SetPropertiesRule(
- new String[] { "id", "final" },
- new String[] { "id", "isFinal" }));
- scxmlRules.add(xp, new DigestSrcAttributeRule(sc));
- }
-
- private static void addInitialRule(String xp,
- ExtendedBaseRules scxmlRules, PathResolver sc, SCXML scxml) {
- scxmlRules.add(xp, new ObjectCreateRule(Initial.class));
- addPseudoStatePropertiesRules(xp, scxmlRules, sc);
- scxmlRules.add(xp, new UpdateModelRule(scxml));
- addTransitionRules(xp + XP_TR, scxmlRules, "setTransition");
- scxmlRules.add(xp, new SetNextRule("setInitial"));
- }
-
- private static void addHistoryRules(String xp,
- ExtendedBaseRules scxmlRules, PathResolver sc, SCXML scxml) {
- scxmlRules.add(xp, new ObjectCreateRule(History.class));
- addPseudoStatePropertiesRules(xp, scxmlRules, sc);
- scxmlRules.add(xp, new UpdateModelRule(scxml));
- scxmlRules.add(xp, new SetPropertiesRule(
- new String[] { "type" }, new String[] { "type" }));
- addTransitionRules(xp + XP_TR, scxmlRules, "setTransition");
- scxmlRules.add(xp, new SetNextRule("addHistory"));
- }
-
- private static void addPseudoStatePropertiesRules(String xp,
- ExtendedBaseRules scxmlRules, PathResolver sc) {
- scxmlRules.add(xp, new SetPropertiesRule(
- new String[] { "id" }, new String[] { "id" }));
- scxmlRules.add(xp, new DigestSrcAttributeRule(sc));
- addParentRule(xp, scxmlRules, 1);
- }
-
- private static void addParentRule(String xp, ExtendedBaseRules scxmlRules,
- final int parent) {
- if (parent < 1) {
- return;
- }
- scxmlRules.add(xp, new Rule() {
- // A generic version of setTopRule
- public void body(String namespace, String name, String text)
- throws Exception {
- TransitionTarget t = (TransitionTarget) getDigester().peek();
- TransitionTarget p = (TransitionTarget) getDigester().peek(
- parent);
- // CHANGE - Moved parent property to TransitionTarget
- t.setParent(p);
- }
- });
- }
-
- private static void addTransitionRules(String xp,
- ExtendedBaseRules scxmlRules, String setNextMethod) {
- scxmlRules.add(xp, new ObjectCreateRule(Transition.class));
- scxmlRules.add(xp, new SetPropertiesRule());
- scxmlRules.add(xp + XP_TAR, new SetPropertiesRule());
- addActionRules(xp, scxmlRules);
- scxmlRules.add(xp + XP_EXT, new Rule() {
- public void end(String namespace, String name) {
- Transition t = (Transition) getDigester().peek(1);
- State exitState = new State();
- exitState.setIsFinal(true);
- t.setTarget(exitState);
- }
- });
- scxmlRules.add(xp, new SetNextRule(setNextMethod));
- }
-
- private static void addHandlerRules(String xp, ExtendedBaseRules scxmlRules) {
- scxmlRules.add(xp + XP_ONEN, new ObjectCreateRule(OnEntry.class));
- addActionRules(xp + XP_ONEN, scxmlRules);
- scxmlRules.add(xp + XP_ONEN, new SetNextRule("setOnEntry"));
- scxmlRules.add(xp + XP_ONEX, new ObjectCreateRule(OnExit.class));
- addActionRules(xp + XP_ONEX, scxmlRules);
- scxmlRules.add(xp + XP_ONEX, new SetNextRule("setOnExit"));
- }
-
- private static void addActionRules(String xp, ExtendedBaseRules scxmlRules) {
- addActionRulesTuple(xp + XP_ASN, scxmlRules, Assign.class);
- addActionRulesTuple(xp + XP_VAR, scxmlRules, Var.class);
- addActionRulesTuple(xp + XP_LOG, scxmlRules, Log.class);
- addActionRulesTuple(xp + XP_SND, scxmlRules, Send.class);
- addActionRulesTuple(xp + XP_CAN, scxmlRules, Cancel.class);
- addActionRulesTuple(xp + XP_EXT, scxmlRules, Exit.class);
- }
-
- private static void addIfRules(String xp, ExtendedBaseRules scxmlRules) {
- addActionRulesTuple(xp, scxmlRules, If.class);
- addActionRules(xp, scxmlRules);
- addActionRulesTuple(xp + XP_EIF, scxmlRules, ElseIf.class);
- addActionRulesTuple(xp + XP_ELS, scxmlRules, Else.class);
- }
-
- private static void addActionRulesTuple(String xp,
- ExtendedBaseRules scxmlRules, Class klass) {
- addSimpleRulesTuple(xp, scxmlRules, klass, null, null, "addAction");
- scxmlRules.add(xp, new SetExecutableParentRule());
- }
-
- private static void addSimpleRulesTuple(String xp,
- ExtendedBaseRules scxmlRules, Class klass, String[] args,
- String[] props, String addMethod) {
- scxmlRules.add(xp, new ObjectCreateRule(klass));
- if (args == null) {
- scxmlRules.add(xp, new SetPropertiesRule());
- } else {
- scxmlRules.add(xp, new SetPropertiesRule(args, props));
- }
- scxmlRules.add(xp, new SetNextRule(addMethod));
- }
-
- /*
- * Post-processing methods to make the SCXML object Executor-ready.
- */
- private static void updateSCXML(SCXML scxml, Context evalCtx,
- Evaluator evalEngine) {
- // Watch case, slightly unfortunate naming ;-)
- String initialstate = scxml.getInitialstate();
- //we have to use getTargets() here since the initialState can be
- //an indirect descendant
- //TODO: better type check, now ClassCastException happens for Parallel
- State initialState = (State) scxml.getTargets().get(initialstate);
- if (initialState == null) {
- // Where do we, where do we go?
- System.err.println("ERROR: SCXMLDigester - No SCXML child state "
- + "with ID \"" + initialstate
- + "\" found i.e. no initialstate" + " for SCXML ;-)");
- }
- scxml.setInitialState(initialState);
- scxml.setRootContext(evalCtx);
- Map targets = scxml.getTargets();
- Map states = scxml.getStates();
- Iterator i = states.keySet().iterator();
- while (i.hasNext()) {
- updateState((State) states.get(i.next()), targets, evalCtx,
- evalEngine);
- }
- }
-
- private static void updateState(State s, Map targets, Context evalCtx,
- Evaluator evalEngine) {
- //setup local variable context
- Context localCtx = null;
- if (s.getParent() == null) {
- localCtx = evalEngine.newContext(evalCtx);
- } else {
- State parentState = null;
- if (s.getParent() instanceof Parallel) {
- parentState = (State) (s.getParent().getParent());
- } else {
- parentState = (State) (s.getParent());
- }
- localCtx = evalEngine.newContext(parentState.getContext());
- }
- s.setContext(localCtx);
- //ensure both onEntry and onExit have parent
- //TODO: add this rather as a Digester rule for OnEntry/OnExit
- s.getOnEntry().setParent(s);
- s.getOnExit().setParent(s);
- //ENDTODO
- //initialize next / inital
- Initial ini = s.getInitial();
- Map c = s.getChildren();
- if (!c.isEmpty()) {
- if (ini == null) {
- System.err.println("WARNING: SCXMLDigester - Initial "
- + "null for " + (SCXMLHelper.isStringEmpty(s.getId()) ?
- "anonymous state" : s.getId()));
- }
- Transition initialTransition = ini.getTransition();
- updateTransition(initialTransition, targets);
- TransitionTarget initialState = initialTransition.getTarget();
- // we have to allow for an indirect descendant initial (targets)
- //check that initialState is a descendant of s
- if (initialState == null || !SCXMLHelper.isDescendant(initialState, s)) {
- System.err.println("WARNING: SCXMLDigester - Initial state "
- + "null or not descendant for " + (SCXMLHelper.
- isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
- }
- }
- List histories = s.getHistory();
- Iterator histIter = histories.iterator();
- while (histIter.hasNext()) {
- History h = (History) histIter.next();
- Transition historyTransition = h.getTransition();
- updateTransition(historyTransition, targets);
- State historyState = (State)historyTransition.getTarget();
- if (historyState == null) {
- System.err.println("WARNING: SCXMLDigester - History state "
- + "null " + (SCXMLHelper.isStringEmpty(s.getId()) ?
- "anonymous state" : s.getId()));
- }
- if (!h.isDeep()) {
- if (!c.containsValue(historyState)) {
- System.err.println("WARNING: SCXMLDigester - History state "
- + "for shallow history is not child for " + (SCXMLHelper.
- isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
- }
- } else {
- if (!SCXMLHelper.isDescendant(historyState, s)) {
- System.err.println("WARNING: SCXMLDigester - History state "
- + "for deep history is not descendant for " + (SCXMLHelper.
- isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
- }
- }
- }
- Map t = s.getTransitions();
- Iterator i = t.keySet().iterator();
- while (i.hasNext()) {
- Iterator j = ((List) t.get(i.next())).iterator();
- while (j.hasNext()) {
- Transition trn = (Transition) j.next();
- // TODO: add this rather as a Digester rule for Transition
- trn.setNotificationRegistry(s.getNotificationRegistry());
- trn.setParent(s);
- // ENDTODO
- updateTransition(trn, targets);
- }
- }
- Parallel p = s.getParallel();
- if (p != null) {
- updateParallel(p, targets, evalCtx, evalEngine);
- } else {
- Iterator j = c.keySet().iterator();
- while (j.hasNext()) {
- updateState((State) c.get(j.next()), targets, evalCtx,
- evalEngine);
- }
- }
- }
-
- private static void updateParallel(Parallel p, Map targets,
- Context evalCtx, Evaluator evalEngine) {
- Iterator i = p.getStates().iterator();
- while (i.hasNext()) {
- updateState((State) i.next(), targets, evalCtx, evalEngine);
- }
- }
-
- private static void updateTransition(Transition t, Map targets) {
- String next = t.getNext();
- TransitionTarget tt = t.getTarget();
- if (tt == null) {
- tt = (TransitionTarget) targets.get(next);
- if (tt == null) {
- // TODO: Move Digester warnings to errors
- System.err.println("WARNING: SCXMLDigester - Transition "
- + "target \"" + next + "\" not found");
- }
- t.setTarget(tt);
- }
- }
-
- /*
- * Private SCXML object serialization utility functions
- */
- private static void serializeState(StringBuffer b, State s, String indent) {
- b.append(indent).append("<state");
- serializeTransitionTargetAttributes(b, s);
- boolean f = s.getIsFinal();
- if (f) {
- b.append(" final=\"true\"");
- }
- b.append(">\n");
- Initial ini = s.getInitial();
- if (ini != null) {
- serializeInitial(b, ini, indent + INDENT);
- }
- List h = s.getHistory();
- if (h != null) {
- serializeHistory(b, h, indent + INDENT);
- }
- serializeOnEntry(b, (TransitionTarget) s, indent + INDENT);
- Map t = s.getTransitions();
- Iterator i = t.keySet().iterator();
- while (i.hasNext()) {
- List et = (List) t.get(i.next());
- for (int len = 0; len < et.size(); len++) {
- serializeTransition(b, (Transition) et.get(len), indent
- + INDENT);
- }
- }
- Parallel p = s.getParallel();
- if (p != null) {
- serializeParallel(b, p, indent + INDENT);
- } else {
- Map c = s.getChildren();
- Iterator j = c.keySet().iterator();
- while (j.hasNext()) {
- State cs = (State) c.get(j.next());
- serializeState(b, cs, indent + INDENT);
- }
- }
- serializeOnExit(b, (TransitionTarget) s, indent + INDENT);
- b.append(indent).append("</state>\n");
- }
-
- private static void serializeParallel(StringBuffer b, Parallel p,
- String indent) {
- b.append(indent).append("<parallel");
- serializeTransitionTargetAttributes(b, p);
- b.append(">\n");
- serializeOnEntry(b, (TransitionTarget) p, indent + INDENT);
- Set s = p.getStates();
- Iterator i = s.iterator();
- while (i.hasNext()) {
- serializeState(b, (State) i.next(), indent + INDENT);
- }
- serializeOnExit(b, (TransitionTarget) p, indent + INDENT);
- b.append(indent).append("</parallel>\n");
- }
-
- private static void serializeInitial(StringBuffer b, Initial i,
- String indent) {
- b.append(indent).append("<initial");
- serializeTransitionTargetAttributes(b, i);
- b.append(">\n");
- serializeTransition(b, i.getTransition(), indent + INDENT);
- b.append(indent).append("</initial>\n");
- }
-
- private static void serializeHistory(StringBuffer b, List l,
- String indent) {
- if (l.size() > 0) {
- for (int i = 0; i < l.size(); i++) {
- History h = (History) l.get(i);
- b.append(indent).append("<history");
- serializeTransitionTargetAttributes(b, h);
- if(h.isDeep()) {
- b.append(" type=\"deep\"");
- } else {
- b.append(" type=\"shallow\"");
- }
- b.append(">\n");
- serializeTransition(b, h.getTransition(), indent + INDENT);
- b.append(indent).append("</history>\n");
- }
- }
- }
-
- private static void serializeTransitionTargetAttributes(StringBuffer b,
- TransitionTarget t) {
- String id = t.getId();
- if (id != null) {
- b.append(" id=\"" + id + "\"");
- }
- TransitionTarget pt = t.getParent();
- if (pt != null) {
- String pid = pt.getId();
- if (pid != null) {
- b.append(" parentid=\"").append(pid).append("\"");
- }
- }
- }
-
- private static void serializeTransition(StringBuffer b, Transition t,
- String indent) {
- b.append(indent).append("<transition event=\"").append(t.getEvent())
- .append("\" cond=\"").append(t.getCond()).append("\">\n");
- boolean exit = serializeActions(b, t.getActions(), indent + INDENT);
- if (!exit) {
- serializeTarget(b, t, indent + INDENT);
- }
- b.append(indent).append("</transition>\n");
- }
-
- private static void serializeTarget(StringBuffer b, Transition t,
- String indent) {
- b.append(indent).append("<target");
- String n = t.getNext();
- if (n != null) {
- b.append(" next=\"" + n + "\">\n");
- } else {
- b.append(">\n");
- if (t.getTarget() != null) {
- // The inline transition target can only be a state
- serializeState(b, (State) t.getTarget(), indent + INDENT);
- }
- }
- b.append(indent).append("</target>\n");
- }
-
- private static void serializeOnEntry(StringBuffer b, TransitionTarget t,
- String indent) {
- OnEntry e = t.getOnEntry();
- if (e != null && e.getActions().size() > 0) {
- b.append(indent).append("<onentry>\n");
- serializeActions(b, e.getActions(), indent + INDENT);
- b.append(indent).append("</onentry>\n");
- }
- }
-
- private static void serializeOnExit(StringBuffer b, TransitionTarget t,
- String indent) {
- OnExit x = t.getOnExit();
- if (x != null && x.getActions().size() > 0) {
- b.append(indent).append("<onexit>\n");
- serializeActions(b, x.getActions(), indent + INDENT);
- b.append(indent).append("</onexit>\n");
- }
- }
-
- private static boolean serializeActions(StringBuffer b, List l,
- String indent) {
- if (l == null) {
- return false;
- }
- boolean exit = false;
- Iterator i = l.iterator();
- while (i.hasNext()) {
- Action a = (Action) i.next();
- // TODO - Serialize action attrs, bodies; Priority: Very low ;-)
- if (a instanceof Var) {
- Var v = (Var) a;
- b.append(indent).append("<var name=\"").append(v.getName())
- .append("\" expr=\"").append(v.getExpr()).append(
- "\"/>\n");
- } else if (a instanceof Assign) {
- Assign asn = (Assign) a;
- b.append(indent).append("<assign name=\"")
- .append(asn.getName()).append("\" expr=\"").append(
- asn.getExpr()).append("\"/>\n");
- } else if (a instanceof Send) {
- Send s = (Send) a;
- b.append(indent).append("<send/>\n");
- } else if (a instanceof Cancel) {
- Cancel c = (Cancel) a;
- b.append(indent).append("<cancel/>\n");
- } else if (a instanceof Log) {
- Log lg = (Log) a;
- b.append(indent).append("<log expr=\"").append(lg.getExpr())
- .append("\"/>\n");
- } else if (a instanceof Exit) {
- Exit e = (Exit) a;
- b.append(indent).append("<exit");
- String expr = e.getExpr();
- String nl = e.getNamelist();
- if (expr != null) {
- b.append(" expr=\"" + expr + "\"");
- }
- if (nl != null) {
- b.append(" namelist=\"" + nl + "\"");
- }
- b.append("/>\n");
- exit = true;
- } else if (a instanceof If) {
- If IF = (If) a;
- serializeIf(b, IF, indent);
- } else if (a instanceof Else) {
- Else el = (Else) a;
- b.append(indent).append("<else/>\n");
- } else if (a instanceof ElseIf) {
- ElseIf eif = (ElseIf) a;
- b.append(indent).append("<elseif cond=\"")
- .append(eif.getCond()).append("\" />\n");
- }
- }
- return exit;
- }
-
- private static void serializeIf(StringBuffer b, If IF, String indent) {
- b.append(indent).append("<if cond=\"").append(IF.getCond()).append(
- "\">\n");
- serializeActions(b, IF.getActions(), indent + INDENT);
- b.append(indent).append("</if>\n");
- }
-
- /**
- * Custom digestion rule for establishing necessary associations within the
- * SCXML object, which include: <br>
- * 1) Updation of the SCXML object's global targets Map <br>
- * 2) Obtaining a handle to the SCXML object's NotificationRegistry <br>
- *
- * @author Rahul Akolkar
- */
- public static class UpdateModelRule extends Rule {
-
- private SCXML scxml;
-
- public UpdateModelRule(SCXML scxml) {
- super();
- this.scxml = scxml;
- }
-
- public void end(String namespace, String name) {
- if (scxml == null) {
- scxml = (SCXML) getDigester()
- .peek(getDigester().getCount() - 1);
- }
- NotificationRegistry notifReg = scxml.getNotificationRegistry();
- TransitionTarget tt = (TransitionTarget) getDigester().peek();
- scxml.addTarget(tt);
- tt.setNotificationRegistry(notifReg);
- }
- }
-
- /**
- * Custom digestion rule for setting Executable parent of Action elements
- *
- * @author Rahul Akolkar
- */
- public static class SetExecutableParentRule extends Rule {
-
- public SetExecutableParentRule() {
- super();
- }
-
- public void end(String namespace, String name) {
- Action child = (Action) getDigester().peek();
- for (int i = 1; i < getDigester().getCount() - 1; i++) {
- Object ancestor = (Object) getDigester().peek(i);
- if (ancestor instanceof Executable) {
- child.setParent((Executable) ancestor);
- return;
- }
- }
- }
- }
-
- /**
- * Custom digestion rule for external sources, that is, the src attribute of
- * the <state> element
- *
- * @author Rahul Akolkar
- */
- public static class DigestSrcAttributeRule extends Rule {
-
- private PathResolver ctx;
-
- public DigestSrcAttributeRule(PathResolver sc) {
- super();
- this.ctx = sc;
- }
-
- public void begin(String namespace, String name, Attributes attributes) {
- String src = attributes.getValue("src");
- if (SCXMLHelper.isStringEmpty(src)) {
- return;
- }
- Digester digester = getDigester();
- SCXML scxml = (SCXML) digester.peek(digester.getCount() - 1);
- // 1) Digest the external SCXML file
- Digester externalSrcDigester = newInstance(scxml, ctx.getResolver(src));
- SCXML externalSCXML = null;
- String path = ctx == null ? src : ctx.resolvePath(src);
-
- try {
- externalSCXML = (SCXML) externalSrcDigester.parse(path);
- } catch (Exception e) {
- log.error(null, e);
- }
- // 2) Adopt the children
- // TODO - Clarify spec; Priority: High
- if (externalSCXML == null) {
- return;
- }
- State s = (State) digester.peek();
- Transition t = new Transition();
- t.setNext(externalSCXML.getInitialstate());
- Initial ini = new Initial();
- ini.setTransition(t);
- s.setInitial(ini);
- Map children = externalSCXML.getStates();
- Object[] ids = children.keySet().toArray();
- for (int i = 0; i < ids.length; i++) {
- s.addChild((State) children.get(ids[i]));
- }
- }
- }
+ // Logging
+ private static org.apache.commons.logging.Log log = LogFactory
+ .getLog(SCXMLDigester.class);
+
+ //-- PUBLIC METHODS --//
+ /**
+ * API for standalone usage where the SCXML document is a URL.
+ *
+ * @param scxmlURL
+ * a canonical absolute URL to parse (relative URLs within the
+ * top level document are to be resovled against this URL).
+ * @param errHandler
+ * The SAX ErrorHandler
+ * @param evalCtx
+ * the document-level variable context for guard condition
+ * evaluation
+ * @param evalEngine
+ * the scripting/expression language engine for creating local
+ * state-level variable contexts (if supported by a given
+ * scripting engine)
+ *
+ * @return SCXML The SCXML object corresponding to the file argument
+ *
+ * @see Context
+ * @see ErrorHandler
+ * @see Evaluator
+ * @see PathResolver
+ */
+ public static SCXML digest(URL scxmlURL, ErrorHandler errHandler,
+ Context evalCtx, Evaluator evalEngine) {
+
+ SCXML scxml = null;
+ Digester scxmlDigester = SCXMLDigester
+ .newInstance(null, new URLResolver(scxmlURL));
+ scxmlDigester.setErrorHandler(errHandler);
+
+ try {
+ scxml = (SCXML) scxmlDigester.parse(scxmlURL.toString());
+ } catch (Exception e) {
+ MessageFormat msgFormat = new MessageFormat(ERR_PARSE_FAIL);
+ String errMsg = msgFormat.format(new Object[] {scxmlURL.toString(),
+ e.getMessage()});
+ log.error(errMsg, e);
+ }
+
+ if (scxml != null) {
+ updateSCXML(scxml, evalCtx, evalEngine);
+ }
+
+ return scxml;
+
+ }
+
+ /**
+ * API for standalone usage where the SCXML document is a URI.
+ * A PathResolver must be provided.
+ *
+ * @param pathResolver
+ * The PathResolver for this context
+ * @param documentRealPath
+ * The String pointing to the absolute (real) path of the
+ * SCXML config
+ * @param errHandler
+ * The SAX ErrorHandler
+ * @param evalCtx
+ * the document-level variable context for guard condition
+ * evaluation
+ * @param evalEngine
+ * the scripting/expression language engine for creating local
+ * state-level variable contexts (if supported by a given
+ * scripting engine)
+ *
+ * @return SCXML The SCXML object corresponding to the file argument
+ *
+ * @see Context
+ * @see ErrorHandler
+ * @see Evaluator
+ * @see PathResolver
+ */
+ public static SCXML digest(String documentRealPath,
+ ErrorHandler errHandler, Context evalCtx, Evaluator evalEngine,
+ PathResolver pr) {
+
+ SCXML scxml = null;
+ Digester scxmlDigester = SCXMLDigester.newInstance(null, pr);
+ scxmlDigester.setErrorHandler(errHandler);
+
+ try {
+ scxml = (SCXML) scxmlDigester.parse(documentRealPath);
+ } catch (Exception e) {
+ MessageFormat msgFormat = new MessageFormat(ERR_PARSE_FAIL);
+ String errMsg = msgFormat.format(new Object[] { documentRealPath,
+ e.getMessage()});
+ log.error(errMsg, e);
+ }
+
+ if (scxml != null) {
+ updateSCXML(scxml, evalCtx, evalEngine);
+ }
+
+ return scxml;
+
+ }
+
+ /**
+ * Serialize this SCXML object (primarily for debugging)
+ *
+ * @param scxml
+ * The SCXML to be serialized
+ * @return String The serialized SCXML
+ */
+ public static String serializeSCXML(SCXML scxml) {
+ StringBuffer b = new StringBuffer("<scxml xmlns=\"").append(
+ scxml.getXmlns()).append("\" version=\"").append(
+ scxml.getVersion()).append("\" initialstate=\"").append(
+ scxml.getInitialstate()).append("\">\n");
+ Map s = scxml.getStates();
+ Iterator i = s.keySet().iterator();
+ while (i.hasNext()) {
+ serializeState(b, (State) s.get(i.next()), INDENT);
+ }
+ b.append("</scxml>\n");
+ return b.toString();
+ }
+
+ //-- PRIVATE CONSTANTS --//
+ //// Patterns to get the digestion going
+ private static final String XP_SM = "scxml";
+
+ private static final String XP_SM_ST = "scxml/state";
+
+ //// Universal matches
+ // State
+ private static final String XP_ST_ST = "!*/state/state";
+
+ private static final String XP_PAR_ST = "!*/parallel/state";
+
+ private static final String XP_TR_TAR_ST = "!*/transition/target/state";
+
+ //private static final String XP_ST_TAR_ST = "!*/state/target/state";
+
+ // Parallel
+ private static final String XP_ST_PAR = "!*/state/parallel";
+
+ // If
+ private static final String XP_IF = "!*/if";
+
+ //// Path Fragments
+ // Onentries and Onexits
+ private static final String XP_ONEN = "/onentry";
+
+ private static final String XP_ONEX = "/onexit";
+
+ // Initial
+ private static final String XP_INI = "/initial";
+
+ // History
+ private static final String XP_HIST = "/history";
+
+ // Transition, target and exit
+ private static final String XP_TR = "/transition";
+
+ private static final String XP_TAR = "/target";
+
+ private static final String XP_ST = "/state";
+
+ private static final String XP_EXT = "/exit";
+
+ // Actions
+ private static final String XP_VAR = "/var";
+
+ private static final String XP_ASN = "/assign";
+
+ private static final String XP_LOG = "/log";
+
+ private static final String XP_SND = "/send";
+
+ private static final String XP_CAN = "/cancel";
+
+ private static final String XP_EIF = "/elseif";
+
+ private static final String XP_ELS = "/else";
+
+ //// Other constants
+ private static final String INDENT = " ";
+
+ //-- PRIVATE UTILITY METHODS --//
+ /*
+ * Get a SCXML digester instance
+ *
+ * @return Digester A newly configured SCXML digester instance
+ */
+ private static Digester newInstance(SCXML scxml, PathResolver sc) {
+
+ Digester digester = new Digester();
+ //Uncomment next line after SCXML DTD is available
+ //digester.setValidating(true);
+ digester.setRules(initRules(scxml, sc));
+ return digester;
+ }
+
+ /*
+ * Private utility functions for configuring digester rule base for SCXML
+ */
+ private static ExtendedBaseRules initRules(SCXML scxml, PathResolver sc) {
+
+ ExtendedBaseRules scxmlRules = new ExtendedBaseRules();
+
+ //// SCXML
+ scxmlRules.add(XP_SM, new ObjectCreateRule(SCXML.class));
+ scxmlRules.add(XP_SM, new SetPropertiesRule());
+
+ //// States
+ // Level one states
+ addStateRules(XP_SM_ST, scxmlRules, scxml, sc, 0);
+ scxmlRules.add(XP_SM_ST, new SetNextRule("addState"));
+ // Nested states
+ addStateRules(XP_ST_ST, scxmlRules, scxml, sc, 1);
+ scxmlRules.add(XP_ST_ST, new SetNextRule("addChild"));
+ // Initial states (no longer needed due to addition of Initial)
+ //addStateRules(XP_ST_TAR_ST, scxmlRules, scxml, sc, 1);
+ //scxmlRules.add(XP_ST_TAR_ST, new SetNextRule("addChild"));
+ //scxmlRules.add(XP_ST_TAR_ST, new SetNextRule("setInitial"));
+ // Parallel states
+ addStateRules(XP_PAR_ST, scxmlRules, scxml, sc, 1);
+ scxmlRules.add(XP_PAR_ST, new SetNextRule("addState"));
+ // Target states
+ addStateRules(XP_TR_TAR_ST, scxmlRules, scxml, sc, 2);
+ scxmlRules.add(XP_TR_TAR_ST, new SetNextRule("setTarget"));
+
+ //// Parallels
+ addParallelRules(XP_ST_PAR, scxmlRules, scxml);
+
+ //// Ifs
+ addIfRules(XP_IF, scxmlRules);
+
+ return scxmlRules;
+
+ }
+
+ private static void addStateRules(String xp, ExtendedBaseRules scxmlRules,
+ SCXML scxml, PathResolver sc, int parent) {
+ scxmlRules.add(xp, new ObjectCreateRule(State.class));
+ addStatePropertiesRules(xp, scxmlRules, sc);
+ //scxmlRules.add(xp + XP_TAR, new SetPropertiesRule());
+ //scxmlRules.add(xp + XP_INI_TR_TAR, new SetPropertiesRule());
+ addInitialRule(xp + XP_INI, scxmlRules, sc, scxml);
+ addHistoryRules(xp + XP_HIST, scxmlRules, sc, scxml);
+ addParentRule(xp, scxmlRules, parent);
+ addTransitionRules(xp + XP_TR, scxmlRules, "addTransition");
+ addHandlerRules(xp, scxmlRules);
+ scxmlRules.add(xp, new UpdateModelRule(scxml));
+ }
+
+ private static void addParallelRules(String xp,
+ ExtendedBaseRules scxmlRules, SCXML scxml) {
+ addSimpleRulesTuple(xp, scxmlRules, Parallel.class, null, null,
+ "setParallel");
+ addHandlerRules(xp, scxmlRules);
+ addParentRule(xp, scxmlRules, 1);
+ scxmlRules.add(xp, new UpdateModelRule(scxml));
+ }
+
+ private static void addStatePropertiesRules(String xp,
+ ExtendedBaseRules scxmlRules, PathResolver sc) {
+ scxmlRules.add(xp, new SetPropertiesRule(
+ new String[] { "id", "final" },
+ new String[] { "id", "isFinal" }));
+ scxmlRules.add(xp, new DigestSrcAttributeRule(sc));
+ }
+
+ private static void addInitialRule(String xp,
+ ExtendedBaseRules scxmlRules, PathResolver sc, SCXML scxml) {
+ scxmlRules.add(xp, new ObjectCreateRule(Initial.class));
+ addPseudoStatePropertiesRules(xp, scxmlRules, sc);
+ scxmlRules.add(xp, new UpdateModelRule(scxml));
+ addTransitionRules(xp + XP_TR, scxmlRules, "setTransition");
+ scxmlRules.add(xp, new SetNextRule("setInitial"));
+ }
+
+ private static void addHistoryRules(String xp,
+ ExtendedBaseRules scxmlRules, PathResolver sc, SCXML scxml) {
+ scxmlRules.add(xp, new ObjectCreateRule(History.class));
+ addPseudoStatePropertiesRules(xp, scxmlRules, sc);
+ scxmlRules.add(xp, new UpdateModelRule(scxml));
+ scxmlRules.add(xp, new SetPropertiesRule(
+ new String[] { "type" }, new String[] { "type" }));
+ addTransitionRules(xp + XP_TR, scxmlRules, "setTransition");
+ scxmlRules.add(xp, new SetNextRule("addHistory"));
+ }
+
+ private static void addPseudoStatePropertiesRules(String xp,
+ ExtendedBaseRules scxmlRules, PathResolver sc) {
+ scxmlRules.add(xp, new SetPropertiesRule(
+ new String[] { "id" }, new String[] { "id" }));
+ scxmlRules.add(xp, new DigestSrcAttributeRule(sc));
+ addParentRule(xp, scxmlRules, 1);
+ }
+
+ private static void addParentRule(String xp, ExtendedBaseRules scxmlRules,
+ final int parent) {
+ if (parent < 1) {
+ return;
+ }
+ scxmlRules.add(xp, new Rule() {
+ // A generic version of setTopRule
+ public void body(String namespace, String name, String text)
+ throws Exception {
+ TransitionTarget t = (TransitionTarget) getDigester().peek();
+ TransitionTarget p = (TransitionTarget) getDigester().peek(
+ parent);
+ // CHANGE - Moved parent property to TransitionTarget
+ t.setParent(p);
+ }
+ });
+ }
+
+ private static void addTransitionRules(String xp,
+ ExtendedBaseRules scxmlRules, String setNextMethod) {
+ scxmlRules.add(xp, new ObjectCreateRule(Transition.class));
+ scxmlRules.add(xp, new SetPropertiesRule());
+ scxmlRules.add(xp + XP_TAR, new SetPropertiesRule());
+ addActionRules(xp, scxmlRules);
+ scxmlRules.add(xp + XP_EXT, new Rule() {
+ public void end(String namespace, String name) {
+ Transition t = (Transition) getDigester().peek(1);
+ State exitState = new State();
+ exitState.setIsFinal(true);
+ t.setTarget(exitState);
+ }
+ });
+ scxmlRules.add(xp, new SetNextRule(setNextMethod));
+ }
+
+ private static void addHandlerRules(String xp, ExtendedBaseRules scxmlRules) {
+ scxmlRules.add(xp + XP_ONEN, new ObjectCreateRule(OnEntry.class));
+ addActionRules(xp + XP_ONEN, scxmlRules);
+ scxmlRules.add(xp + XP_ONEN, new SetNextRule("setOnEntry"));
+ scxmlRules.add(xp + XP_ONEX, new ObjectCreateRule(OnExit.class));
+ addActionRules(xp + XP_ONEX, scxmlRules);
+ scxmlRules.add(xp + XP_ONEX, new SetNextRule("setOnExit"));
+ }
+
+ private static void addActionRules(String xp, ExtendedBaseRules scxmlRules) {
+ addActionRulesTuple(xp + XP_ASN, scxmlRules, Assign.class);
+ addActionRulesTuple(xp + XP_VAR, scxmlRules, Var.class);
+ addActionRulesTuple(xp + XP_LOG, scxmlRules, Log.class);
+ addActionRulesTuple(xp + XP_SND, scxmlRules, Send.class);
+ addActionRulesTuple(xp + XP_CAN, scxmlRules, Cancel.class);
+ addActionRulesTuple(xp + XP_EXT, scxmlRules, Exit.class);
+ }
+
+ private static void addIfRules(String xp, ExtendedBaseRules scxmlRules) {
+ addActionRulesTuple(xp, scxmlRules, If.class);
+ addActionRules(xp, scxmlRules);
+ addActionRulesTuple(xp + XP_EIF, scxmlRules, ElseIf.class);
+ addActionRulesTuple(xp + XP_ELS, scxmlRules, Else.class);
+ }
+
+ private static void addActionRulesTuple(String xp,
+ ExtendedBaseRules scxmlRules, Class klass) {
+ addSimpleRulesTuple(xp, scxmlRules, klass, null, null, "addAction");
+ scxmlRules.add(xp, new SetExecutableParentRule());
+ }
+
+ private static void addSimpleRulesTuple(String xp,
+ ExtendedBaseRules scxmlRules, Class klass, String[] args,
+ String[] props, String addMethod) {
+ scxmlRules.add(xp, new ObjectCreateRule(klass));
+ if (args == null) {
+ scxmlRules.add(xp, new SetPropertiesRule());
+ } else {
+ scxmlRules.add(xp, new SetPropertiesRule(args, props));
+ }
+ scxmlRules.add(xp, new SetNextRule(addMethod));
+ }
+
+ /*
+ * Post-processing methods to make the SCXML object Executor-ready.
+ */
+ private static void updateSCXML(SCXML scxml, Context evalCtx,
+ Evaluator evalEngine) {
+ // Watch case, slightly unfortunate naming ;-)
+ String initialstate = scxml.getInitialstate();
+ //we have to use getTargets() here since the initialState can be
+ //an indirect descendant
+ //TODO: better type check, now ClassCastException happens for Parallel
+ State initialState = (State) scxml.getTargets().get(initialstate);
+ if (initialState == null) {
+ // Where do we, where do we go?
+ System.err.println("ERROR: SCXMLDigester - No SCXML child state "
+ + "with ID \"" + initialstate
+ + "\" found i.e. no initialstate" + " for SCXML ;-)");
+ }
+ scxml.setInitialState(initialState);
+ scxml.setRootContext(evalCtx);
+ Map targets = scxml.getTargets();
+ Map states = scxml.getStates();
+ Iterator i = states.keySet().iterator();
+ while (i.hasNext()) {
+ updateState((State) states.get(i.next()), targets, evalCtx,
+ evalEngine);
+ }
+ }
+
+ private static void updateState(State s, Map targets, Context evalCtx,
+ Evaluator evalEngine) {
+ //setup local variable context
+ Context localCtx = null;
+ if (s.getParent() == null) {
+ localCtx = evalEngine.newContext(evalCtx);
+ } else {
+ State parentState = null;
+ if (s.getParent() instanceof Parallel) {
+ parentState = (State) (s.getParent().getParent());
+ } else {
+ parentState = (State) (s.getParent());
+ }
+ localCtx = evalEngine.newContext(parentState.getContext());
+ }
+ s.setContext(localCtx);
+ //ensure both onEntry and onExit have parent
+ //TODO: add this rather as a Digester rule for OnEntry/OnExit
+ s.getOnEntry().setParent(s);
+ s.getOnExit().setParent(s);
+ //ENDTODO
+ //initialize next / inital
+ Initial ini = s.getInitial();
+ Map c = s.getChildren();
+ if (!c.isEmpty()) {
+ if (ini == null) {
+ System.err.println("WARNING: SCXMLDigester - Initial "
+ + "null for " + (SCXMLHelper.isStringEmpty(s.getId()) ?
+ "anonymous state" : s.getId()));
+ }
+ Transition initialTransition = ini.getTransition();
+ updateTransition(initialTransition, targets);
+ TransitionTarget initialState = initialTransition.getTarget();
+ // we have to allow for an indirect descendant initial (targets)
+ //check that initialState is a descendant of s
+ if (initialState == null || !SCXMLHelper.isDescendant(initialState, s)) {
+ System.err.println("WARNING: SCXMLDigester - Initial state "
+ + "null or not descendant for " + (SCXMLHelper.
+ isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
+ }
+ }
+ List histories = s.getHistory();
+ Iterator histIter = histories.iterator();
+ while (histIter.hasNext()) {
+ History h = (History) histIter.next();
+ Transition historyTransition = h.getTransition();
+ updateTransition(historyTransition, targets);
+ State historyState = (State)historyTransition.getTarget();
+ if (historyState == null) {
+ System.err.println("WARNING: SCXMLDigester - History state "
+ + "null " + (SCXMLHelper.isStringEmpty(s.getId()) ?
+ "anonymous state" : s.getId()));
+ }
+ if (!h.isDeep()) {
+ if (!c.containsValue(historyState)) {
+ System.err.println("WARNING: SCXMLDigester - History state "
+ + "for shallow history is not child for " + (SCXMLHelper.
+ isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
+ }
+ } else {
+ if (!SCXMLHelper.isDescendant(historyState, s)) {
+ System.err.println("WARNING: SCXMLDigester - History state "
+ + "for deep history is not descendant for " + (SCXMLHelper.
+ isStringEmpty(s.getId()) ? "anonymous state" : s.getId()));
+ }
+ }
+ }
+ Map t = s.getTransitions();
+ Iterator i = t.keySet().iterator();
+ while (i.hasNext()) {
+ Iterator j = ((List) t.get(i.next())).iterator();
+ while (j.hasNext()) {
+ Transition trn = (Transition) j.next();
+ // TODO: add this rather as a Digester rule for Transition
+ trn.setNotificationRegistry(s.getNotificationRegistry());
+ trn.setParent(s);
+ // ENDTODO
+ updateTransition(trn, targets);
+ }
+ }
+ Parallel p = s.getParallel();
+ if (p != null) {
+ updateParallel(p, targets, evalCtx, evalEngine);
+ } else {
+ Iterator j = c.keySet().iterator();
+ while (j.hasNext()) {
+ updateState((State) c.get(j.next()), targets, evalCtx,
+ evalEngine);
+ }
+ }
+ }
+
+ private static void updateParallel(Parallel p, Map targets,
+ Context evalCtx, Evaluator evalEngine) {
+ Iterator i = p.getStates().iterator();
+ while (i.hasNext()) {
+ updateState((State) i.next(), targets, evalCtx, evalEngine);
+ }
+ }
+
+ private static void updateTransition(Transition t, Map targets) {
+ String next = t.getNext();
+ TransitionTarget tt = t.getTarget();
+ if (tt == null) {
+ tt = (TransitionTarget) targets.get(next);
+ if (tt == null) {
+ // TODO: Move Digester warnings to errors
+ System.err.println("WARNING: SCXMLDigester - Transition "
+ + "target \"" + next + "\" not found");
+ }
+ t.setTarget(tt);
+ }
+ }
+
+ /*
+ * Private SCXML object serialization utility functions
+ */
+ private static void serializeState(StringBuffer b, State s, String indent) {
+ b.append(indent).append("<state");
+ serializeTransitionTargetAttributes(b, s);
+ boolean f = s.getIsFinal();
+ if (f) {
+ b.append(" final=\"true\"");
+ }
+ b.append(">\n");
+ Initial ini = s.getInitial();
+ if (ini != null) {
+ serializeInitial(b, ini, indent + INDENT);
+ }
+ List h = s.getHistory();
+ if (h != null) {
+ serializeHistory(b, h, indent + INDENT);
+ }
+ serializeOnEntry(b, (TransitionTarget) s, indent + INDENT);
+ Map t = s.getTransitions();
+ Iterator i = t.keySet().iterator();
+ while (i.hasNext()) {
+ List et = (List) t.get(i.next());
+ for (int len = 0; len < et.size(); len++) {
+ serializeTransition(b, (Transition) et.get(len), indent
+ + INDENT);
+ }
+ }
+ Parallel p = s.getParallel();
+ if (p != null) {
+ serializeParallel(b, p, indent + INDENT);
+ } else {
+ Map c = s.getChildren();
+ Iterator j = c.keySet().iterator();
+ while (j.hasNext()) {
+ State cs = (State) c.get(j.next());
+ serializeState(b, cs, indent + INDENT);
+ }
+ }
+ serializeOnExit(b, (TransitionTarget) s, indent + INDENT);
+ b.append(indent).append("</state>\n");
+ }
+
+ private static void serializeParallel(StringBuffer b, Parallel p,
+ String indent) {
+ b.append(indent).append("<parallel");
+ serializeTransitionTargetAttributes(b, p);
+ b.append(">\n");
+ serializeOnEntry(b, (TransitionTarget) p, indent + INDENT);
+ Set s = p.getStates();
+ Iterator i = s.iterator();
+ while (i.hasNext()) {
+ serializeState(b, (State) i.next(), indent + INDENT);
+ }
+ serializeOnExit(b, (TransitionTarget) p, indent + INDENT);
+ b.append(indent).append("</parallel>\n");
+ }
+
+ private static void serializeInitial(StringBuffer b, Initial i,
+ String indent) {
+ b.append(indent).append("<initial");
+ serializeTransitionTargetAttributes(b, i);
+ b.append(">\n");
+ serializeTransition(b, i.getTransition(), indent + INDENT);
+ b.append(indent).append("</initial>\n");
+ }
+
+ private static void serializeHistory(StringBuffer b, List l,
+ String indent) {
+ if (l.size() > 0) {
+ for (int i = 0; i < l.size(); i++) {
+ History h = (History) l.get(i);
+ b.append(indent).append("<history");
+ serializeTransitionTargetAttributes(b, h);
+ if(h.isDeep()) {
+ b.append(" type=\"deep\"");
+ } else {
+ b.append(" type=\"shallow\"");
+ }
+ b.append(">\n");
+ serializeTransition(b, h.getTransition(), indent + INDENT);
+ b.append(indent).append("</history>\n");
+ }
+ }
+ }
+
+ private static void serializeTransitionTargetAttributes(StringBuffer b,
+ TransitionTarget t) {
+ String id = t.getId();
+ if (id != null) {
+ b.append(" id=\"" + id + "\"");
+ }
+ TransitionTarget pt = t.getParent();
+ if (pt != null) {
+ String pid = pt.getId();
+ if (pid != null) {
+ b.append(" parentid=\"").append(pid).append("\"");
+ }
+ }
+ }
+
+ private static void serializeTransition(StringBuffer b, Transition t,
+ String indent) {
+ b.append(indent).append("<transition event=\"").append(t.getEvent())
+ .append("\" cond=\"").append(t.getCond()).append("\">\n");
+ boolean exit = serializeActions(b, t.getActions(), indent + INDENT);
+ if (!exit) {
+ serializeTarget(b, t, indent + INDENT);
+ }
+ b.append(indent).append("</transition>\n");
+ }
+
+ private static void serializeTarget(StringBuffer b, Transition t,
+ String indent) {
+ b.append(indent).append("<target");
+ String n = t.getNext();
+ if (n != null) {
+ b.append(" next=\"" + n + "\">\n");
+ } else {
+ b.append(">\n");
+ if (t.getTarget() != null) {
+ // The inline transition target can only be a state
+ serializeState(b, (State) t.getTarget(), indent + INDENT);
+ }
+ }
+ b.append(indent).append("</target>\n");
+ }
+
+ private static void serializeOnEntry(StringBuffer b, TransitionTarget t,
+ String indent) {
+ OnEntry e = t.getOnEntry();
+ if (e != null && e.getActions().size() > 0) {
+ b.append(indent).append("<onentry>\n");
+ serializeActions(b, e.getActions(), indent + INDENT);
+ b.append(indent).append("</onentry>\n");
+ }
+ }
+
+ private static void serializeOnExit(StringBuffer b, TransitionTarget t,
+ String indent) {
+ OnExit x = t.getOnExit();
+ if (x != null && x.getActions().size() > 0) {
+ b.append(indent).append("<onexit>\n");
+ serializeActions(b, x.getActions(), indent + INDENT);
+ b.append(indent).append("</onexit>\n");
+ }
+ }
+
+ private static boolean serializeActions(StringBuffer b, List l,
+ String indent) {
+ if (l == null) {
+ return false;
+ }
+ boolean exit = false;
+ Iterator i = l.iterator();
+ while (i.hasNext()) {
+ Action a = (Action) i.next();
+ // TODO - Serialize action attrs, bodies; Priority: Very low ;-)
+ if (a instanceof Var) {
+ Var v = (Var) a;
+ b.append(indent).append("<var name=\"").append(v.getName())
+ .append("\" expr=\"").append(v.getExpr()).append(
+ "\"/>\n");
+ } else if (a instanceof Assign) {
+ Assign asn = (Assign) a;
+ b.append(indent).append("<assign name=\"")
+ .append(asn.getName()).append("\" expr=\"").append(
+ asn.getExpr()).append("\"/>\n");
+ } else if (a instanceof Send) {
+ Send s = (Send) a;
+ b.append(indent).append("<send/>\n");
+ } else if (a instanceof Cancel) {
+ Cancel c = (Cancel) a;
+ b.append(indent).append("<cancel/>\n");
+ } else if (a instanceof Log) {
+ Log lg = (Log) a;
+ b.append(indent).append("<log expr=\"").append(lg.getExpr())
+ .append("\"/>\n");
+ } else if (a instanceof Exit) {
+ Exit e = (Exit) a;
+ b.append(indent).append("<exit");
+ String expr = e.getExpr();
+ String nl = e.getNamelist();
+ if (expr != null) {
+ b.append(" expr=\"" + expr + "\"");
+ }
+ if (nl != null) {
+ b.append(" namelist=\"" + nl + "\"");
+ }
+ b.append("/>\n");
+ exit = true;
+ } else if (a instanceof If) {
+ If IF = (If) a;
+ serializeIf(b, IF, indent);
+ } else if (a instanceof Else) {
+ Else el = (Else) a;
+ b.append(indent).append("<else/>\n");
+ } else if (a instanceof ElseIf) {
+ ElseIf eif = (ElseIf) a;
+ b.append(indent).append("<elseif cond=\"")
+ .append(eif.getCond()).append("\" />\n");
+ }
+ }
+ return exit;
+ }
+
+ private static void serializeIf(StringBuffer b, If IF, String indent) {
+ b.append(indent).append("<if cond=\"").append(IF.getCond()).append(
+ "\">\n");
+ serializeActions(b, IF.getActions(), indent + INDENT);
+ b.append(indent).append("</if>\n");
+ }
+
+ /**
+ * Custom digestion rule for establishing necessary associations within the
+ * SCXML object, which include: <br>
+ * 1) Updation of the SCXML object's global targets Map <br>
+ * 2) Obtaining a handle to the SCXML object's NotificationRegistry <br>
+ *
+ * @author Rahul Akolkar
+ */
+ public static class UpdateModelRule extends Rule {
+
+ private SCXML scxml;
+
+ public UpdateModelRule(SCXML scxml) {
+ super();
+ this.scxml = scxml;
+ }
+
+ public void end(String namespace, String name) {
+ if (scxml == null) {
+ scxml = (SCXML) getDigester()
+ .peek(getDigester().getCount() - 1);
+ }
+ NotificationRegistry notifReg = scxml.getNotificationRegistry();
+ TransitionTarget tt = (TransitionTarget) getDigester().peek();
+ scxml.addTarget(tt);
+ tt.setNotificationRegistry(notifReg);
+ }
+ }
+
+ /**
+ * Custom digestion rule for setting Executable parent of Action elements
+ *
+ * @author Rahul Akolkar
+ */
+ public static class SetExecutableParentRule extends Rule {
+
+ public SetExecutableParentRule() {
+ super();
+ }
+
+ public void end(String namespace, String name) {
+ Action child = (Action) getDigester().peek();
+ for (int i = 1; i < getDigester().getCount() - 1; i++) {
+ Object ancestor = (Object) getDigester().peek(i);
+ if (ancestor instanceof Executable) {
+ child.setParent((Executable) ancestor);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Custom digestion rule for external sources, that is, the src attribute of
+ * the <state> element
+ *
+ * @author Rahul Akolkar
+ */
+ public static class DigestSrcAttributeRule extends Rule {
+
+ private PathResolver ctx;
+
+ public DigestSrcAttributeRule(PathResolver sc) {
+ super();
+ this.ctx = sc;
+ }
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ String src = attributes.getValue("src");
+ if (SCXMLHelper.isStringEmpty(src)) {
+ return;
+ }
+ Digester digester = getDigester();
+ SCXML scxml = (SCXML) digester.peek(digester.getCount() - 1);
+ // 1) Digest the external SCXML file
+ Digester externalSrcDigester = newInstance(scxml, ctx.getResolver(src));
+ SCXML externalSCXML = null;
+ String path = ctx == null ? src : ctx.resolvePath(src);
+
+ try {
+ externalSCXML = (SCXML) externalSrcDigester.parse(path);
+ } catch (Exception e) {
+ log.error(null, e);
+ }
+ // 2) Adopt the children
+ // TODO - Clarify spec; Priority: High
+ if (externalSCXML == null) {
+ return;
+ }
+ State s = (State) digester.peek();
+ Transition t = new Transition();
+ t.setNext(externalSCXML.getInitialstate());
+ Initial ini = new Initial();
+ ini.setTransition(t);
+ s.setInitial(ini);
+ Map children = externalSCXML.getStates();
+ Object[] ids = children.keySet().toArray();
+ for (int i = 0; i < ids.length; i++) {
+ s.addChild((State) children.get(ids[i]));
+ }
+ }
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExecutor.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExecutor.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExecutor.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExecutor.java Wed Aug 10 14:10:59 2005
@@ -37,9 +37,9 @@
* @see SCXMLSemantics
*/
public class SCXMLExecutor {
-
- private static Log log = LogFactory.getLog(SCXMLExecutor.class);
-
+
+ private static Log log = LogFactory.getLog(SCXMLExecutor.class);
+
/**
* The stateMachine being executed
*/
@@ -48,7 +48,7 @@
/**
* The evaluator for expressions
*/
- private Evaluator evaluator;
+ private Evaluator evaluator;
/**
* The current status of the stateMachine
@@ -63,85 +63,85 @@
/**
* The environment specific error reporter
*/
- private ErrorReporter errorReporter = null;
-
- /**
- * Run-to-completion
- */
- private boolean superStep = true;
-
- /**
- * Interpretation semantics
- * (not configurable without re-compilation for now,
- * since we have one implementation anyway)
- */
- private SCXMLSemantics semantics = new SCXMLSemantics();
-
+ private ErrorReporter errorReporter = null;
+
+ /**
+ * Run-to-completion
+ */
+ private boolean superStep = true;
+
+ /**
+ * Interpretation semantics
+ * (not configurable without re-compilation for now,
+ * since we have one implementation anyway)
+ */
+ private SCXMLSemantics semantics = new SCXMLSemantics();
+
/**
* The worker method. Re-evaluates current status whenever any events
* are triggered.
*
- * @param evts
- * an array of external events which triggered during the last
- * time quantum
+ * @param evts
+ * an array of external events which triggered during the last
+ * time quantum
* @throws ModelException in case there is a fatal SCXML object
* model problem.
- */
- public void triggerEvents(TriggerEvent evts[])
- throws ModelException {
- ArrayList evs = new ArrayList(Arrays.asList(evts));
- do {
- // CreateStep
- Step step = new Step(evs, currentStatus);
- // EnumerateReachableTransitions
- semantics.enumerateReachableTransitions(stateMachine, step,
- errorReporter);
- // FilterTransitionSet
- semantics.filterTransitionsSet(step, evaluator, errorReporter);
- // SeedTargetSet
- semantics.seedTargetSet(step, errorReporter);
- // DetermineTargetStates
- semantics.determineTargetStates(
- step.getAfterStatus().getStates(), errorReporter);
- // BuildOnExitOnEntryLists
- semantics.buildOnExitOnEntryLists(step, errorReporter);
- // UpdateHistoryStates
- semantics.updateHistoryStates(step, errorReporter);
- // ExecuteActions
- semantics.executeActions(step, this, errorReporter);
- // AssignCurrentStatus
- updateStatus(step);
- // ***Cleanup external events if superStep
- if(superStep) {
- evs.clear();
- }
- } while(superStep && currentStatus.getEvents().size() > 0);
- logState();
- }
+ */
+ public void triggerEvents(TriggerEvent evts[])
+ throws ModelException {
+ ArrayList evs = new ArrayList(Arrays.asList(evts));
+ do {
+ // CreateStep
+ Step step = new Step(evs, currentStatus);
+ // EnumerateReachableTransitions
+ semantics.enumerateReachableTransitions(stateMachine, step,
+ errorReporter);
+ // FilterTransitionSet
+ semantics.filterTransitionsSet(step, evaluator, errorReporter);
+ // SeedTargetSet
+ semantics.seedTargetSet(step, errorReporter);
+ // DetermineTargetStates
+ semantics.determineTargetStates(
+ step.getAfterStatus().getStates(), errorReporter);
+ // BuildOnExitOnEntryLists
+ semantics.buildOnExitOnEntryLists(step, errorReporter);
+ // UpdateHistoryStates
+ semantics.updateHistoryStates(step, errorReporter);
+ // ExecuteActions
+ semantics.executeActions(step, this, errorReporter);
+ // AssignCurrentStatus
+ updateStatus(step);
+ // ***Cleanup external events if superStep
+ if(superStep) {
+ evs.clear();
+ }
+ } while(superStep && currentStatus.getEvents().size() > 0);
+ logState();
+ }
- public SCXMLExecutor() throws ModelException {
- this(null, null, null);
- }
+ public SCXMLExecutor() throws ModelException {
+ this(null, null, null);
+ }
- /**
- * Constructor
- *
- * @param stateMachine The stateMachine to execute
- * @param evaluator The expression evaluator
- * @param evtDisp The event dispatcher
- * @param errRep The error reporter
- * @throws ModelException in case there is a fatal SCXML object
- * model problem.
- */
- public SCXMLExecutor(Evaluator evaluator, EventDispatcher evtDisp,
- ErrorReporter errRep) throws ModelException {
- this.evaluator = evaluator;
- this.eventdispatcher = evtDisp;
- this.errorReporter = errRep;
- this.currentStatus = null;
- this.stateMachine = null;
- }
-
+ /**
+ * Constructor
+ *
+ * @param stateMachine The stateMachine to execute
+ * @param evaluator The expression evaluator
+ * @param evtDisp The event dispatcher
+ * @param errRep The error reporter
+ * @throws ModelException in case there is a fatal SCXML object
+ * model problem.
+ */
+ public SCXMLExecutor(Evaluator evaluator, EventDispatcher evtDisp,
+ ErrorReporter errRep) throws ModelException {
+ this.evaluator = evaluator;
+ this.eventdispatcher = evtDisp;
+ this.errorReporter = errRep;
+ this.currentStatus = null;
+ this.stateMachine = null;
+ }
+
/**
* Clear all state and begin from "initialstate" indicated
* on root SCXML element.
@@ -149,168 +149,168 @@
* @throws ModelException in case there is a fatal SCXML object
* model problem.
*/
- public void reset() throws ModelException {
- // Reset all variable contexts
- stateMachine.getRootContext().reset();
- // all states and parallels, only states have var. contexts
- for (Iterator i = stateMachine.getTargets().values().iterator();
- i.hasNext();) {
- TransitionTarget tt = (TransitionTarget)i.next();
- if(tt instanceof State) {
- ((State)tt).getContext().reset();
- }
- }
- // CreateEmptyStatus
- currentStatus = new Status();
- Step step = new Step(null, currentStatus);
- // DetermineInitialStates
- semantics.determineInitialStates(stateMachine,
- step.getAfterStatus().getStates(),
- step.getEntryList(), errorReporter);
- // ExecuteActions
- semantics.executeActions(step, this, errorReporter);
- // AssignCurrentStatus
- updateStatus(step);
- // Execute Immediate Transitions
- if(superStep && currentStatus.getEvents().size() > 0) {
- this.triggerEvents(new TriggerEvent[0]);
- } else {
- logState();
- }
+ public void reset() throws ModelException {
+ // Reset all variable contexts
+ stateMachine.getRootContext().reset();
+ // all states and parallels, only states have var. contexts
+ for (Iterator i = stateMachine.getTargets().values().iterator();
+ i.hasNext();) {
+ TransitionTarget tt = (TransitionTarget)i.next();
+ if(tt instanceof State) {
+ ((State)tt).getContext().reset();
+ }
+ }
+ // CreateEmptyStatus
+ currentStatus = new Status();
+ Step step = new Step(null, currentStatus);
+ // DetermineInitialStates
+ semantics.determineInitialStates(stateMachine,
+ step.getAfterStatus().getStates(),
+ step.getEntryList(), errorReporter);
+ // ExecuteActions
+ semantics.executeActions(step, this, errorReporter);
+ // AssignCurrentStatus
+ updateStatus(step);
+ // Execute Immediate Transitions
+ if(superStep && currentStatus.getEvents().size() > 0) {
+ this.triggerEvents(new TriggerEvent[0]);
+ } else {
+ logState();
+ }
}
- /**
- * Get the current status
- *
+ /**
+ * Get the current status
+ *
* @return The current Status
*/
public Status getCurrentStatus() {
return currentStatus;
}
- /**
- * Get the expression evaluator
- *
- * @return Returns the evaluator.
- */
- public Evaluator getEvaluator() {
- return evaluator;
- }
-
- /**
- * @param evaluator The evaluator to set.
- */
- public void setEvaluator(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- /**
- * Get the state machine that is being executed
- *
- * @return Returns the stateMachine.
- */
- public SCXML getStateMachine() {
- return stateMachine;
- }
-
- /**
- * Set the state machine to be executed
- *
- * @param stateMachine The stateMachine to set.
- * @throws ModelException in case there is a fatal SCXML object
- * model problem.
- */
- public void setStateMachine(SCXML statemachine) throws ModelException {
- // NormalizeStateMachine
- SCXML sm = semantics.normalizeStateMachine(statemachine,
- errorReporter);
- // StoreStateMachine
- this.stateMachine = sm;
- // reset
- this.reset();
- }
-
- /**
- * Get the environment specific error reporter
- *
- * @return Returns the errorReporter.
- */
- public ErrorReporter getErrorReporter() {
- return errorReporter;
- }
-
- /**
- * Set the environment specific error reporter
- *
- * @param errorReporter The errorReporter to set.
- */
- public void setErrorReporter(ErrorReporter errorReporter) {
- this.errorReporter = errorReporter;
- }
-
- /**
- * Get the event dispatcher
- *
- * @return Returns the eventdispatcher.
- */
- public EventDispatcher getEventdispatcher() {
- return eventdispatcher;
- }
-
- /**
- * Set the event dispatcher
- *
- * @param eventdispatcher The eventdispatcher to set.
- */
- public void setEventdispatcher(EventDispatcher eventdispatcher) {
- this.eventdispatcher = eventdispatcher;
- }
-
- /**
- * Use "super-step", default is <code>true</code>
- * (that is, run-to-completion is default)
- * @return Returns the superStep property.
- * @see #setSuperStep(boolean)
- */
- public boolean isSuperStep() {
- return superStep;
- }
-
- /**
- * Set the super step
- * @param superStep
- * if true, the internal derived events are also processed (run-to-completion);
- * if false, the internal derived events are stored in the
- * CurrentStatus property and processed within the next
- * triggerEvents() invocation, also the immediate (empty event) transitions
- * are deferred until the next step
- */
- public void setSuperStep(boolean superStep) {
- this.superStep = superStep;
- }
-
+ /**
+ * Get the expression evaluator
+ *
+ * @return Returns the evaluator.
+ */
+ public Evaluator getEvaluator() {
+ return evaluator;
+ }
+
+ /**
+ * @param evaluator The evaluator to set.
+ */
+ public void setEvaluator(Evaluator evaluator) {
+ this.evaluator = evaluator;
+ }
+
+ /**
+ * Get the state machine that is being executed
+ *
+ * @return Returns the stateMachine.
+ */
+ public SCXML getStateMachine() {
+ return stateMachine;
+ }
+
+ /**
+ * Set the state machine to be executed
+ *
+ * @param stateMachine The stateMachine to set.
+ * @throws ModelException in case there is a fatal SCXML object
+ * model problem.
+ */
+ public void setStateMachine(SCXML statemachine) throws ModelException {
+ // NormalizeStateMachine
+ SCXML sm = semantics.normalizeStateMachine(statemachine,
+ errorReporter);
+ // StoreStateMachine
+ this.stateMachine = sm;
+ // reset
+ this.reset();
+ }
+
+ /**
+ * Get the environment specific error reporter
+ *
+ * @return Returns the errorReporter.
+ */
+ public ErrorReporter getErrorReporter() {
+ return errorReporter;
+ }
+
+ /**
+ * Set the environment specific error reporter
+ *
+ * @param errorReporter The errorReporter to set.
+ */
+ public void setErrorReporter(ErrorReporter errorReporter) {
+ this.errorReporter = errorReporter;
+ }
+
+ /**
+ * Get the event dispatcher
+ *
+ * @return Returns the eventdispatcher.
+ */
+ public EventDispatcher getEventdispatcher() {
+ return eventdispatcher;
+ }
+
+ /**
+ * Set the event dispatcher
+ *
+ * @param eventdispatcher The eventdispatcher to set.
+ */
+ public void setEventdispatcher(EventDispatcher eventdispatcher) {
+ this.eventdispatcher = eventdispatcher;
+ }
+
+ /**
+ * Use "super-step", default is <code>true</code>
+ * (that is, run-to-completion is default)
+ * @return Returns the superStep property.
+ * @see #setSuperStep(boolean)
+ */
+ public boolean isSuperStep() {
+ return superStep;
+ }
+
+ /**
+ * Set the super step
+ * @param superStep
+ * if true, the internal derived events are also processed (run-to-completion);
+ * if false, the internal derived events are stored in the
+ * CurrentStatus property and processed within the next
+ * triggerEvents() invocation, also the immediate (empty event) transitions
+ * are deferred until the next step
+ */
+ public void setSuperStep(boolean superStep) {
+ this.superStep = superStep;
+ }
+
private void logState() {
- if(log.isInfoEnabled()) {
- Iterator si = currentStatus.getStates().iterator();
- StringBuffer sb = new StringBuffer("Current States: [");
- while(si.hasNext()) {
- State s = (State)si.next();
- sb.append(s.getId());
- if(si.hasNext()) {
- sb.append(", ");
- }
- }
- sb.append(']');
- log.info(sb.toString());
- }
- }
+ if(log.isInfoEnabled()) {
+ Iterator si = currentStatus.getStates().iterator();
+ StringBuffer sb = new StringBuffer("Current States: [");
+ while(si.hasNext()) {
+ State s = (State)si.next();
+ sb.append(s.getId());
+ if(si.hasNext()) {
+ sb.append(", ");
+ }
+ }
+ sb.append(']');
+ log.info(sb.toString());
+ }
+ }
- /**
- * @param step
- */
- private void updateStatus(Step step) {
- this.currentStatus = step.getAfterStatus();
- stateMachine.getRootContext().setLocal("_ALL_STATES",
- SCXMLHelper.getAncestorClosure(currentStatus.getStates(), null));
- }
+ /**
+ * @param step
+ */
+ private void updateStatus(Step step) {
+ this.currentStatus = step.getAfterStatus();
+ stateMachine.getRootContext().setLocal("_ALL_STATES",
+ SCXMLHelper.getAncestorClosure(currentStatus.getStates(), null));
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExpressionException.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExpressionException.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExpressionException.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLExpressionException.java Wed Aug 10 14:10:59 2005
@@ -26,36 +26,36 @@
*/
public class SCXMLExpressionException extends Exception {
- /**
- * @see java.lang.Exception#Exception()
- */
- public SCXMLExpressionException() {
- super();
- }
+ /**
+ * @see java.lang.Exception#Exception()
+ */
+ public SCXMLExpressionException() {
+ super();
+ }
- /**
- * @see java.lang.Exception#Exception(java.lang.String)
- * @param message
- */
- public SCXMLExpressionException(String message) {
- super(message);
- }
+ /**
+ * @see java.lang.Exception#Exception(java.lang.String)
+ * @param message
+ */
+ public SCXMLExpressionException(String message) {
+ super(message);
+ }
- /**
- * @see java.lang.Exception#Exception(java.lang.Throwable)
- * @param cause
- */
- public SCXMLExpressionException(Throwable cause) {
- super(cause);
- }
-
- /**
- * @see java.lang.Exception#Exception(java.lang.String, java.lang.Throwable)
- * @param message
- * @param cause
- */
- public SCXMLExpressionException(String message, Throwable cause) {
- super(message, cause);
- }
+ /**
+ * @see java.lang.Exception#Exception(java.lang.Throwable)
+ * @param cause
+ */
+ public SCXMLExpressionException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @see java.lang.Exception#Exception(java.lang.String, java.lang.Throwable)
+ * @param message
+ * @param cause
+ */
+ public SCXMLExpressionException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: taglibs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: taglibs-dev-help@jakarta.apache.org