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 [11/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/SCXMLHelper.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLHelper.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLHelper.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLHelper.java Wed Aug 10 14:10:59 2005
@@ -35,233 +35,233 @@
*/
public class SCXMLHelper {
- /**
- * Return true if the string is empty
- *
- * @param attr The String to test
- * @return Is string empty
- */
- public static final boolean isStringEmpty(String attr) {
- return (attr == null || attr.trim().length() == 0) ? true : false;
- }
-
- /**
- * Checks whether a transition target tt (State or Parallel) is a descendant
- * of the transition target ctx.
- *
- * @param tt
- * TransitionTarget to check - a potential descendant
- * @param ctx
- * TransitionTarget context - a potential ancestor
- * @return true iff tt is a descendant of ctx, false otherwise
- */
- public static final boolean isDescendant(TransitionTarget tt,
- TransitionTarget ctx) {
- while ((tt = tt.getParent()) != null) {
- if (tt == ctx) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Creates a set which contains given states and all their ancestors
- * recursively up to the upper bound. Null upperBound means root
- * of the state machine.
- *
- * @param upperBounds
- * @param transTargets
- * [in]
- *
- * @return transitive closure of a given state set
- */
- public static final Set getAncestorClosure(Set states, Set upperBounds) {
- Set closure = new HashSet((int) (states.size() * 2));
- for (Iterator i = states.iterator(); i.hasNext();) {
- TransitionTarget tt = (TransitionTarget) i.next();
- closure.add(tt);
- while ((tt = tt.getParent()) != null) {
- if (upperBounds != null && upperBounds.contains(tt)) {
- break;
- }
- if (!closure.add(tt)) {
- //parent is already a part of the closure
- break;
- }
- }
- }
- return closure;
- }
-
- /**
- * Checks whether a given set of states is a legal Harel State Table
- * configuration (with the respect to the definition of the OR and AND
- * states).
- *
- * @param states
- * a set of states
- * @param errRep
- * ErrorReporter to report detailed error info if needed
- * @return true if a given state configuration is legal, false otherwise
- */
- public static final boolean isLegalConfig(Set states, ErrorReporter errRep) {
- /*
- * For every active state we add 1 to the count of its parent. Each
- * Parallel should reach count equal to the number of its children and
- * contribute by 1 to its parent. Each State should reach count exactly
- * 1. SCXML elemnt (top) should reach count exactly 1. We essentially
- * summarize up the hierarchy tree starting with a given set of states =
- * active configuration.
- */
- boolean legalConfig = true; // let's be optimists
- Map counts = new IdentityHashMap();
- Set scxmlCount = new HashSet();
- for (Iterator i = states.iterator(); i.hasNext();) {
- TransitionTarget tt = (TransitionTarget) i.next();
- TransitionTarget parent = null;
- while ((parent = tt.getParent()) != null) {
- HashSet cnt = (HashSet) counts.get(parent);
- if (cnt == null) {
- cnt = new HashSet();
- counts.put(parent, cnt);
- }
- cnt.add(tt);
- tt = parent;
- }
- //top-level contribution
- scxmlCount.add(tt);
- }
- //Validate counts:
- for (Iterator i = counts.entrySet().iterator(); i.hasNext();) {
- Map.Entry entry = (Map.Entry) i.next();
- TransitionTarget tt = (TransitionTarget) entry.getKey();
- Set count = (Set) entry.getValue();
- if (tt instanceof Parallel) {
- Parallel p = (Parallel) tt;
- if (count.size() < p.getStates().size()) {
- errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
- "Not all AND states active for parallel "
- + p.getId(), entry);
- legalConfig = false;
- }
- } else {
- if (count.size() > 1) {
- errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
- "Multiple OR states active for state "
- + tt.getId(), entry);
- legalConfig = false;
- }
- }
- count.clear(); //cleanup
- }
- if (scxmlCount.size() > 1) {
- errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
- "Multiple top-level OR states active!", scxmlCount);
- }
- //cleanup
- scxmlCount.clear();
- counts.clear();
- return legalConfig;
- }
-
- /**
- * finds the least common ancestor of transition targets tt1 and tt2 if one
- * exists.
- *
- * @param tt1
- * @param tt2
- * @return closest common ancestor of tt1 and tt2 or null
- */
- public static final TransitionTarget getLCA(TransitionTarget tt1,
- TransitionTarget tt2) {
- if (tt1 == tt2) {
- return tt1; //self-transition
- } else if (isDescendant(tt1, tt2)) {
- return tt2;
- } else if (isDescendant(tt2, tt1)) {
- return tt1;
- }
- Set parents = new HashSet();
- TransitionTarget tmp = tt1;
- while ((tmp = tmp.getParent()) != null) {
- if (tmp instanceof State) {
- parents.add(tmp);
- }
- }
- tmp = tt2;
- while ((tmp = tmp.getParent()) != null) {
- if (tmp instanceof State) {
- //test redundant add = common ancestor
- if (!parents.add(tmp)) {
- parents.clear();
- return tmp;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the set of all states (and parallels) which are exited if a given transition t is
- * going to be taken. Current states are necessary to be taken into account
- * due to orthogonal states and cross-region transitions - see UML specs.
- * for more details.
- *
- * @param t
- * transition to be taken
- * @param currentStates
- * the set of current states (simple states only)
- * @return a set of all states (including composite) which are exited if a
- * given transition is taken
- */
- public static final Set getStatesExited(Transition t, Set currentStates) {
- Set allStates = new HashSet();
- Path p = t.getPath();
- //the easy part
- allStates.addAll(p.getUpwardSegment());
- if (p.isCrossRegion()) {
- for (Iterator regions = p.getRegionsExited().iterator();
- regions.hasNext(); ) {
- Parallel par = ((Parallel) ((State) regions.next()).getParent());
- //let's find affected states in sibling regions
- for (Iterator siblings = par.getStates().iterator();
- siblings.hasNext(); ) {
- State s = (State) siblings.next();
- for (Iterator act = currentStates.iterator();
- act.hasNext(); ) {
- TransitionTarget a = (TransitionTarget) act.next();
- if (isDescendant(a, s)) {
- //a is affected
- boolean added = false;
- added = allStates.add(a);
- while (added && a != s) {
- a = a.getParent();
- added = allStates.add(a);
- }
- }
- }
- }
- }
- }
- return allStates;
- }
-
- /**
- * According to the UML definition, two transitions
- * are conflicting if the sets of states they exit overlap.
- *
- * @param t1 a transition to check against t2
- * @param t2 a transition to check against t1
- * @param currentStates the set of current states (simple states only)
- * @return true if the t1 and t2 are conflicting transitions
- * @see #getStatesExited(Transition, Set)
- */
- public static final boolean inConflict(Transition t1, Transition t2,
- Set currentStates) {
- Set ts1 = getStatesExited(t1, currentStates);
- Set ts2 = getStatesExited(t2, currentStates);
- ts1.retainAll(ts2);
- return (ts1.isEmpty()) ? false : true;
- }
+ /**
+ * Return true if the string is empty
+ *
+ * @param attr The String to test
+ * @return Is string empty
+ */
+ public static final boolean isStringEmpty(String attr) {
+ return (attr == null || attr.trim().length() == 0) ? true : false;
+ }
+
+ /**
+ * Checks whether a transition target tt (State or Parallel) is a descendant
+ * of the transition target ctx.
+ *
+ * @param tt
+ * TransitionTarget to check - a potential descendant
+ * @param ctx
+ * TransitionTarget context - a potential ancestor
+ * @return true iff tt is a descendant of ctx, false otherwise
+ */
+ public static final boolean isDescendant(TransitionTarget tt,
+ TransitionTarget ctx) {
+ while ((tt = tt.getParent()) != null) {
+ if (tt == ctx) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a set which contains given states and all their ancestors
+ * recursively up to the upper bound. Null upperBound means root
+ * of the state machine.
+ *
+ * @param upperBounds
+ * @param transTargets
+ * [in]
+ *
+ * @return transitive closure of a given state set
+ */
+ public static final Set getAncestorClosure(Set states, Set upperBounds) {
+ Set closure = new HashSet((int) (states.size() * 2));
+ for (Iterator i = states.iterator(); i.hasNext();) {
+ TransitionTarget tt = (TransitionTarget) i.next();
+ closure.add(tt);
+ while ((tt = tt.getParent()) != null) {
+ if (upperBounds != null && upperBounds.contains(tt)) {
+ break;
+ }
+ if (!closure.add(tt)) {
+ //parent is already a part of the closure
+ break;
+ }
+ }
+ }
+ return closure;
+ }
+
+ /**
+ * Checks whether a given set of states is a legal Harel State Table
+ * configuration (with the respect to the definition of the OR and AND
+ * states).
+ *
+ * @param states
+ * a set of states
+ * @param errRep
+ * ErrorReporter to report detailed error info if needed
+ * @return true if a given state configuration is legal, false otherwise
+ */
+ public static final boolean isLegalConfig(Set states, ErrorReporter errRep) {
+ /*
+ * For every active state we add 1 to the count of its parent. Each
+ * Parallel should reach count equal to the number of its children and
+ * contribute by 1 to its parent. Each State should reach count exactly
+ * 1. SCXML elemnt (top) should reach count exactly 1. We essentially
+ * summarize up the hierarchy tree starting with a given set of states =
+ * active configuration.
+ */
+ boolean legalConfig = true; // let's be optimists
+ Map counts = new IdentityHashMap();
+ Set scxmlCount = new HashSet();
+ for (Iterator i = states.iterator(); i.hasNext();) {
+ TransitionTarget tt = (TransitionTarget) i.next();
+ TransitionTarget parent = null;
+ while ((parent = tt.getParent()) != null) {
+ HashSet cnt = (HashSet) counts.get(parent);
+ if (cnt == null) {
+ cnt = new HashSet();
+ counts.put(parent, cnt);
+ }
+ cnt.add(tt);
+ tt = parent;
+ }
+ //top-level contribution
+ scxmlCount.add(tt);
+ }
+ //Validate counts:
+ for (Iterator i = counts.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ TransitionTarget tt = (TransitionTarget) entry.getKey();
+ Set count = (Set) entry.getValue();
+ if (tt instanceof Parallel) {
+ Parallel p = (Parallel) tt;
+ if (count.size() < p.getStates().size()) {
+ errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
+ "Not all AND states active for parallel "
+ + p.getId(), entry);
+ legalConfig = false;
+ }
+ } else {
+ if (count.size() > 1) {
+ errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
+ "Multiple OR states active for state "
+ + tt.getId(), entry);
+ legalConfig = false;
+ }
+ }
+ count.clear(); //cleanup
+ }
+ if (scxmlCount.size() > 1) {
+ errRep.onError(ErrorReporter.ILLEGAL_CONFIG,
+ "Multiple top-level OR states active!", scxmlCount);
+ }
+ //cleanup
+ scxmlCount.clear();
+ counts.clear();
+ return legalConfig;
+ }
+
+ /**
+ * finds the least common ancestor of transition targets tt1 and tt2 if one
+ * exists.
+ *
+ * @param tt1
+ * @param tt2
+ * @return closest common ancestor of tt1 and tt2 or null
+ */
+ public static final TransitionTarget getLCA(TransitionTarget tt1,
+ TransitionTarget tt2) {
+ if (tt1 == tt2) {
+ return tt1; //self-transition
+ } else if (isDescendant(tt1, tt2)) {
+ return tt2;
+ } else if (isDescendant(tt2, tt1)) {
+ return tt1;
+ }
+ Set parents = new HashSet();
+ TransitionTarget tmp = tt1;
+ while ((tmp = tmp.getParent()) != null) {
+ if (tmp instanceof State) {
+ parents.add(tmp);
+ }
+ }
+ tmp = tt2;
+ while ((tmp = tmp.getParent()) != null) {
+ if (tmp instanceof State) {
+ //test redundant add = common ancestor
+ if (!parents.add(tmp)) {
+ parents.clear();
+ return tmp;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of all states (and parallels) which are exited if a given transition t is
+ * going to be taken. Current states are necessary to be taken into account
+ * due to orthogonal states and cross-region transitions - see UML specs.
+ * for more details.
+ *
+ * @param t
+ * transition to be taken
+ * @param currentStates
+ * the set of current states (simple states only)
+ * @return a set of all states (including composite) which are exited if a
+ * given transition is taken
+ */
+ public static final Set getStatesExited(Transition t, Set currentStates) {
+ Set allStates = new HashSet();
+ Path p = t.getPath();
+ //the easy part
+ allStates.addAll(p.getUpwardSegment());
+ if (p.isCrossRegion()) {
+ for (Iterator regions = p.getRegionsExited().iterator();
+ regions.hasNext(); ) {
+ Parallel par = ((Parallel) ((State) regions.next()).getParent());
+ //let's find affected states in sibling regions
+ for (Iterator siblings = par.getStates().iterator();
+ siblings.hasNext(); ) {
+ State s = (State) siblings.next();
+ for (Iterator act = currentStates.iterator();
+ act.hasNext(); ) {
+ TransitionTarget a = (TransitionTarget) act.next();
+ if (isDescendant(a, s)) {
+ //a is affected
+ boolean added = false;
+ added = allStates.add(a);
+ while (added && a != s) {
+ a = a.getParent();
+ added = allStates.add(a);
+ }
+ }
+ }
+ }
+ }
+ }
+ return allStates;
+ }
+
+ /**
+ * According to the UML definition, two transitions
+ * are conflicting if the sets of states they exit overlap.
+ *
+ * @param t1 a transition to check against t2
+ * @param t2 a transition to check against t1
+ * @param currentStates the set of current states (simple states only)
+ * @return true if the t1 and t2 are conflicting transitions
+ * @see #getStatesExited(Transition, Set)
+ */
+ public static final boolean inConflict(Transition t1, Transition t2,
+ Set currentStates) {
+ Set ts1 = getStatesExited(t1, currentStates);
+ Set ts2 = getStatesExited(t2, currentStates);
+ ts1.retainAll(ts2);
+ return (ts1.isEmpty()) ? false : true;
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLListener.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLListener.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLListener.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLListener.java Wed Aug 10 14:10:59 2005
@@ -26,29 +26,29 @@
* @author Jaroslav Gergic
*/
public interface SCXMLListener {
-
- /**
- * Handle the entry into a TransitionTarget
- *
- * @param state The TransitionTarget entered
- */
- public void onEntry(TransitionTarget state);
+
+ /**
+ * Handle the entry into a TransitionTarget
+ *
+ * @param state The TransitionTarget entered
+ */
+ public void onEntry(TransitionTarget state);
- /**
- * Handle the exit out of a TransitionTarget
- *
- * @param state The TransitionTarget exited
- */
- public void onExit(TransitionTarget state);
+ /**
+ * Handle the exit out of a TransitionTarget
+ *
+ * @param state The TransitionTarget exited
+ */
+ public void onExit(TransitionTarget state);
- /**
- * Handle the transition
- *
- * @param from The source TransitionTarget
- * @param to The destination TransitionTarget
- * @param transition The Transition taken
- */
- public void onTransition(TransitionTarget from, TransitionTarget to,
- Transition transition);
+ /**
+ * Handle the transition
+ *
+ * @param from The source TransitionTarget
+ * @param to The destination TransitionTarget
+ * @param transition The Transition taken
+ */
+ public void onTransition(TransitionTarget from, TransitionTarget to,
+ Transition transition);
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLSemantics.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLSemantics.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLSemantics.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/SCXMLSemantics.java Wed Aug 10 14:10:59 2005
@@ -80,660 +80,660 @@
*/
public class SCXMLSemantics {
- protected static org.apache.commons.logging.Log appLog = LogFactory
- .getLog("scxml.app.log");
+ protected static org.apache.commons.logging.Log appLog = LogFactory
+ .getLog("scxml.app.log");
- protected TransitionTargetComparator ttc = new TransitionTargetComparator();
+ protected TransitionTargetComparator ttc = new TransitionTargetComparator();
- /**
- * @param input
- * SCXML state machine
- * @return normalized SCXML state machine, pseudo states are removed, etc.
- * @param errRep
- * ErrorReporter callback
- */
- public SCXML normalizeStateMachine(SCXML input, ErrorReporter errRep) {
- //it is a no-op for now
- return input;
- }
-
- /**
- * @param input
- * SCXML state machine [in]
- * @param states
- * a set of States to populate [out]
- * @param entryList
- * a list of States and Parallels to enter [out]
- * @param errRep
- * ErrorReporter callback [inout]
- * @throws ModelException
- * in case there is a fatal SCXML object model problem.
- */
- public void determineInitialStates(SCXML input, Set states, List entryList,
- ErrorReporter errRep) throws ModelException {
- State tmp = input.getInitialState();
- if (tmp == null) {
- errRep.onError(ErrorReporter.NO_INITIAL,
- "SCXML initialstate is missing!", input);
- } else {
- states.add(tmp);
- determineTargetStates(states, errRep);
- //set of ALL entered states (even if initialState is a jump-over)
- Set onEntry = SCXMLHelper.getAncestorClosure(states, null);
- // sort onEntry according state hierarchy
- Object oen[] = onEntry.toArray();
- onEntry.clear();
- Arrays.sort(oen, getTTComparator());
- // we need to impose reverse order for the onEntry list
- List entering = Arrays.asList(oen);
- Collections.reverse(entering);
- entryList.addAll(entering);
-
- }
- }
-
- /**
- * @param actions
- * a list of actions to execute [in]
- * @param derivedEvents
- * collection of internal events generated by the actions [out]
- * @param exec
- * execution environment [inout]
- * @throws ModelException
- * in case there is a fatal SCXML object model problem.
- * @throws SCXMLExpressionException
- * @see ErrorReporter
- * @see NotificationRegistry
- * @see EventDispatcher
- * @see Context
- * @see Evaluator
- */
- public void executeActionList(List actions, Collection derivedEvents,
- SCXMLExecutor exec, ErrorReporter errRep) throws ModelException,
- SCXMLExpressionException {
- // NOTE: "if" statement is a container - we may need to call this method
- // recursively and pass a sub-list of actions embedded in a particular
- // "if"
- Evaluator eval = exec.getEvaluator();
- for (Iterator i = actions.iterator(); i.hasNext(); ) {
- Action a = (Action) i.next();
- State parentState = a.getParentState();
- Context ctx = parentState.getContext();
- // NOTE: "elseif" and "else" do not appear here, since they are
- // always handled as a part of "if" as a container
- if (a instanceof Assign) {
- Assign asgn = (Assign) a;
- String varName = asgn.getName();
- if (!ctx.has(varName)) {
- errRep.onError(ErrorReporter.UNDEFINED_VARIABLE, varName
- + " = null", parentState);
- } else {
- Object varObj = eval.eval(ctx, asgn.getExpr());
- ctx.set(varName, varObj);
- TriggerEvent ev = new TriggerEvent(varName + ".change",
- TriggerEvent.CHANGE_EVENT);
- derivedEvents.add(ev);
- }
- } else if (a instanceof Cancel) {
- Cancel cncl = (Cancel) a;
- exec.getEventdispatcher().cancel(cncl.getSendId());
- } else if (a instanceof Exit) {
- // Ignore; Exit instance holds other information that might
- // be needed, and is not transformed at parse time.
- //throw new ModelException("The <exit/> tag must be transformed"
- // + " to an anonymous final state at the parse time!");
- } else if (a instanceof If) {
- //determine elseif/else separators evaluate conditions
- //extract a sub-list of If's actions and invoke
- // executeActionList()
- List todoList = new LinkedList();
- If ifo = (If) a;
- List subAct = ifo.getActions();
- boolean cnd = eval.evalCond(ctx, ifo.getCond()).booleanValue();
- for (Iterator ifiter = subAct.iterator(); ifiter.hasNext(); ) {
- Action aa = (Action) ifiter.next();
- if (cnd && !(aa instanceof ElseIf) && !(aa instanceof Else)) {
- todoList.add(aa);
- } else if (cnd
- && (aa instanceof ElseIf || aa instanceof Else)) {
- break;
- } else if (aa instanceof ElseIf) {
- cnd = eval.evalCond(ctx, ((ElseIf) aa).getCond())
- .booleanValue();
- } else if (aa instanceof Else) {
- cnd = true;
- } else {
- //skip
- }
- }
- if (!todoList.isEmpty()) {
- executeActionList(todoList, derivedEvents, exec, errRep);
- }
- todoList.clear();
- } else if (a instanceof Log) {
- Log lg = (Log) a;
- Object exprRslt = eval.eval(ctx, lg.getExpr());
- appLog.info(lg.getLabel() + ": " + String.valueOf(exprRslt));
- } else if (a instanceof Send) {
- Send snd = (Send) a;
- Object hints = null;
- if (!SCXMLHelper.isStringEmpty(snd.getHints())) {
- hints = eval.eval(ctx, snd.getHints());
- }
- Map params = null;
- if (!SCXMLHelper.isStringEmpty(snd.getNamelist())) {
- StringTokenizer tkn = new StringTokenizer(snd.getNamelist());
- params = new HashMap(tkn.countTokens());
- while (tkn.hasMoreTokens()) {
- String varName = tkn.nextToken();
- Object varObj = ctx.get(varName);
- if (varObj == null) {
- //considered as a warning here
- errRep.onError(ErrorReporter.UNDEFINED_VARIABLE,
- varName + " = null", parentState);
- }
- params.put(varName, varObj);
- }
- }
- exec.getEventdispatcher().send(snd.getSendId(),
- snd.getTarget(), snd.getTargetType(), snd.getEvent(),
- params, hints, Long.parseLong(snd.getDelay()));
- } else if (a instanceof Var) {
- Var vr = (Var) a;
- String varName = vr.getName();
- Object varObj = eval.eval(ctx, vr.getExpr());
- ctx.setLocal(varName, varObj);
- TriggerEvent ev = new TriggerEvent(varName + ".change",
- TriggerEvent.CHANGE_EVENT);
- derivedEvents.add(ev);
- } else {
- errRep.onError(ErrorReporter.UNKNOWN_ACTION,
- "unsupported executable statement", a);
- }
- }
- }
-
- /**
- * Exectutes all OnExit/Transition/OnEntry transitional actions.
- *
- * @param step
- * [inout] provides EntryList, TransitList, ExitList gets updated
- * its AfterStatus/Events
- * @param exec
- * [inout] execution environment - SCXMLExecutor instance
- * @param errRep
- * [out[ error reporter
- * @throws ModelException
- * in case there is a fatal SCXML object model problem.
- */
- public void executeActions(Step step, SCXMLExecutor exec,
- ErrorReporter errRep) throws ModelException {
- SCXML sm = exec.getStateMachine();
- NotificationRegistry nr = sm.getNotificationRegistry();
- Collection internalEvents = step.getAfterStatus().getEvents();
- // ExecutePhaseActions / OnExit
- for (Iterator i = step.getExitList().iterator(); i.hasNext(); ) {
- TransitionTarget tt = (TransitionTarget) i.next();
- OnExit oe = tt.getOnExit();
- try {
- executeActionList(oe.getActions(), internalEvents, exec, errRep);
- } catch (SCXMLExpressionException e) {
- errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
- oe);
- }
- nr.fireOnExit(tt, tt);
- nr.fireOnExit(sm, tt);
- TriggerEvent te = new TriggerEvent(tt.getId() + ".exit",
- TriggerEvent.CHANGE_EVENT);
- internalEvents.add(te);
- }
- // ExecutePhaseActions / Transitions
- for (Iterator i = step.getTransitList().iterator(); i.hasNext(); ) {
- Transition t = (Transition) i.next();
- try {
- executeActionList(t.getActions(), internalEvents, exec, errRep);
- } catch (SCXMLExpressionException e) {
- errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
- t);
- }
- nr.fireOnTransition(t, t.getParent(), t.getRuntimeTarget(), t);
- nr.fireOnTransition(sm, t.getParent(), t.getRuntimeTarget(), t);
- }
- // ExecutePhaseActions / OnEntry
- for (Iterator i = step.getEntryList().iterator(); i.hasNext(); ) {
- TransitionTarget tt = (TransitionTarget) i.next();
- OnEntry oe = tt.getOnEntry();
- try {
- executeActionList(oe.getActions(), internalEvents, exec, errRep);
- } catch (SCXMLExpressionException e) {
- errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
- oe);
- }
- nr.fireOnEntry(tt, tt);
- nr.fireOnEntry(sm, tt);
- TriggerEvent te = new TriggerEvent(tt.getId() + ".entry",
- TriggerEvent.CHANGE_EVENT);
- internalEvents.add(te);
- //3.2.1 and 3.4 (.done events)
- if (tt instanceof State) {
- State ts = (State)tt;
- if (ts.getIsFinal()) {
- State parent = (State)ts.getParent();
- String prefix = (parent == null) ? "" : parent.getId();
- te = new TriggerEvent(prefix + ".done",
- TriggerEvent.CHANGE_EVENT);
- internalEvents.add(te);
- if (parent != null) {
- parent.setDone(true);
- }
- if (parent != null && parent.isRegion()) {
- //3.4 we got a region, which is finalized
- //let's check its siblings too
- Parallel p = (Parallel)parent.getParent();
- int finCount = 0;
- int pCount = p.getStates().size();
- Iterator regions = p.getStates().iterator();
- while(regions.hasNext()) {
- State reg = (State)regions.next();
- if(reg.isDone()) {
- finCount++;
- }
- }
- if(finCount == pCount) {
- te = new TriggerEvent(p.getId() + ".done",
- TriggerEvent.CHANGE_EVENT);
- internalEvents.add(te);
- te = new TriggerEvent(p.getParent().getId() + ".done",
- TriggerEvent.CHANGE_EVENT);
- internalEvents.add(te);
- //this is not in the specs, but is makes sense
- p.getParentState().setDone(true);
- }
- }
- }
- }
- }
- }
-
- /**
- * @param stateMachine
- * a SM to traverse [in]
- * @param step
- * with current status and list of transitions to populate
- * [inout]
- * @param errRep
- * ErrorReporter callback [inout]
- */
- public void enumerateReachableTransitions(SCXML stateMachine, Step step,
- ErrorReporter errRep) {
- // prevents adding the same transition multiple times
- Set transSet = new HashSet();
- // prevents visiting the same state multiple times
- Set stateSet = new HashSet(step.getBeforeStatus().getStates());
- // breath-first search to-do list
- LinkedList todoList = new LinkedList(stateSet);
- while (!todoList.isEmpty()) {
- State st = (State) todoList.removeFirst();
- for (Iterator i = st.getTransitionsList().iterator(); i.hasNext(); ) {
- Transition t = (Transition) i.next();
- if (!transSet.contains(t)) {
- transSet.add(t);
- step.getTransitList().add(t);
- }
- }
- State parent = st.getParentState();
- if (parent != null && !stateSet.contains(parent)) {
- stateSet.add(parent);
- todoList.addLast(parent);
- }
- }
- transSet.clear();
- stateSet.clear();
- todoList.clear();
- }
-
- /**
- * @param step
- * [inout]
- * @param evaluator
- * guard condition evaluator
- * @param errRep
- * ErrorReporter callback [inout]
- */
- public void filterTransitionsSet(Step step, Evaluator evaluator,
- ErrorReporter errRep) {
- /*
- * - filter transition set by applying events (step/beforeStatus/events +
- * step/externalEvents) (local check) - evaluating guard conditions for
- * each transition (local check) - transition precedence (bottom-up) as
- * defined by SCXML specs
- */
- Set allEvents = new HashSet(step.getBeforeStatus().getEvents()
- .size()
- + step.getExternalEvents().size());
- //for now, we only match against event names
- for (Iterator ei = step.getBeforeStatus().getEvents().iterator();
- ei.hasNext(); ) {
- TriggerEvent te = (TriggerEvent) ei.next();
- allEvents.add(te.getName());
- }
- for (Iterator ei = step.getExternalEvents().iterator(); ei.hasNext(); ) {
- TriggerEvent te = (TriggerEvent) ei.next();
- allEvents.add(te.getName());
- }
- //remove list (filtered-out list)
- List removeList = new LinkedList();
- //iterate over non-filtered transition set
- for (Iterator iter = step.getTransitList().iterator(); iter.hasNext();) {
- Transition t = (Transition) iter.next();
- // event check
- String event = t.getEvent();
- if (!eventMatch(event, allEvents)) {
- // t has a non-empty event which is not triggered
- removeList.add(t);
- continue; //makes no sense to eval guard cond.
- }
- // guard condition check
- Boolean rslt;
- String expr = t.getCond();
- if (SCXMLHelper.isStringEmpty(expr)) {
- rslt = Boolean.TRUE;
- } else {
- try {
- rslt = evaluator.evalCond(((State) t.getParent())
- .getContext(), t.getCond());
- } catch (SCXMLExpressionException e) {
- rslt = Boolean.FALSE;
- errRep.onError(ErrorReporter.EXPRESSION_ERROR, e
- .getMessage(), t);
- }
- }
- if (rslt.booleanValue() == false) {
- // guard condition has not passed
- removeList.add(t);
- }
- }
- // apply event + guard condition filter
- step.getTransitList().removeAll(removeList);
- // cleanup temporary structures
- allEvents.clear();
- removeList.clear();
- // optimization - global precedence potentially applies
- // only if there are multiple enabled transitions
- if (step.getTransitList().size() > 1) {
- // global transition precedence check
- Object trans[] = step.getTransitList().toArray();
- Set currentStates = step.getBeforeStatus().getStates();
- // non-determinism candidates
- Set nonDeterm = new HashSet();
- for (int i = 0; i < trans.length; i++) {
- Transition t = (Transition) trans[i];
- TransitionTarget tsrc = t.getParent();
- for (int j = i + 1; j < trans.length; j++) {
- Transition t2 = (Transition) trans[j];
- boolean conflict = SCXMLHelper.inConflict(t, t2,
- currentStates);
- if (conflict) {
- //potentially conflicting transitions
- TransitionTarget t2src = t2.getParent();
- if (SCXMLHelper.isDescendant(t2src, tsrc)) {
- //t2 takes precedence over t
- removeList.add(t);
- break; //it makes no sense to waste cycles with t
- } else if (SCXMLHelper.isDescendant(tsrc, t2src)) {
- //t takes precendence over t2
- removeList.add(t2);
- } else {
- //add both to the non-determinism candidates
- nonDeterm.add(t);
- nonDeterm.add(t2);
- }
- }
- }
- }
- // check if all non-deterministic situations have been resolved
- nonDeterm.removeAll(removeList);
- if (nonDeterm.size() > 0) {
- errRep.onError(ErrorReporter.NON_DETERMINISTIC,
- "Multiple conflicting transitions enabled.", nonDeterm);
- }
- // apply global transition filter
- step.getTransitList().removeAll(removeList);
- removeList.clear();
- nonDeterm.clear();
- }
- }
-
- /**
- * @param step
- * transitional step
- * @param errRep
- * ErrorReporter callback [inout]
- */
- public void seedTargetSet(Step step, ErrorReporter errRep) {
- Set sources = step.getBeforeStatus().getStates();
- Set targets = step.getAfterStatus().getStates();
- List transitions = step.getTransitList();
- /* populate the target set by taking targets of selected transitions */
- for (Iterator i = transitions.iterator(); i.hasNext(); ) {
- Transition t = (Transition) i.next();
- targets.add(t.getRuntimeTarget());
- }
- /* retain the source states, which are not affected by the transitions */
- for (Iterator i = sources.iterator(); i.hasNext(); ) {
- State s = (State) i.next();
- boolean retain = true;
- for (Iterator j = transitions.iterator(); j.hasNext(); ) {
- Transition t = (Transition) j.next();
- State ts = (State) t.getParent();
- if (s == ts || SCXMLHelper.isDescendant(s, ts)) {
- retain = false;
- break;
- }
- }
- if (retain) {
- targets.add(s);
- }
- }
- }
-
- /**
- * @param states
- * a set seeded in previous step [inout]
- * @param errRep
- * ErrorReporter callback [inout]
- * @see #seedTargetSet(Step, ErrorReporter)
- */
- public void determineTargetStates(Set states, ErrorReporter errRep)
- throws ModelException {
- LinkedList wrkSet = new LinkedList(states);
- // clear the seed-set - will be populated by leaf states
- states.clear();
- while (!wrkSet.isEmpty()) {
- TransitionTarget tt = (TransitionTarget) wrkSet.removeFirst();
- if (tt instanceof State) {
- State st = (State) tt;
- //state can either have parallel or substates w. initial
- //or it is a leaf state
- // NOTE: Digester has to verify this precondition!
- if (st.isSimple()) {
- states.add(st); //leaf
- } else if (st.isOrthogonal()) {
- wrkSet.addLast(st.getParallel()); //parallel
- } else {
- // composite state
- Initial ini = st.getInitial();
- if (ini == null) {
- errRep.onError(ErrorReporter.NO_INITIAL,
- "Initial pseudostate is missing!", st);
- }
- // If we are here, transition target must be a State
- // or History
- TransitionTarget init = ini.getTransition().getTarget();
- if (init == null
- || !(init instanceof State || init instanceof History)) {
- errRep.onError(ErrorReporter.ILLEGAL_INITIAL,
- "Initial does not point to a State or a History!",
- st);
- } else {
- wrkSet.addLast(init);
- }
- }
- } else if (tt instanceof Parallel) {
- Parallel prl = (Parallel) tt;
- Iterator i = prl.getStates().iterator();
- while (i.hasNext()) {
- //fork
- wrkSet.addLast(i.next());
- }
- } else if (tt instanceof History) {
- History h = (History) tt;
- if (h.isEmpty()) {
- wrkSet.addLast(h.getTransition().getRuntimeTarget());
- } else {
- wrkSet.addAll(h.getLastConfiguration());
- }
- } else {
- throw new ModelException("Unknown TransitionTarget subclass:"
- + tt.getClass().getName());
- }
- }
- if (!SCXMLHelper.isLegalConfig(states, errRep)) {
- throw new ModelException("Illegal state machine configuration!");
- }
- }
-
- /**
- * @param step
- * [inout]
- * @param errRep
- * ErrorReporter callback [inout]
- */
- public void buildOnExitOnEntryLists(Step step, ErrorReporter errRep) {
- //set of exited states
- Set onExit = SCXMLHelper.getAncestorClosure(step.getBeforeStatus()
- .getStates(), null);
- Set onExit2 = new HashSet(onExit);
- //set of entered states
- Set onEntry = SCXMLHelper.getAncestorClosure(step.getAfterStatus()
- .getStates(), null);
- //remove common sub-set
- onExit.removeAll(onEntry);
- onEntry.removeAll(onExit2);
- //explicitly add self-transitions
- for (Iterator i = step.getTransitList().iterator(); i.hasNext(); ) {
- Transition t = (Transition) i.next();
- if (t.getParent() == t.getTarget()) {
- onExit.add(t.getParent());
- onEntry.add(t.getTarget());
- }
- }
- // sort onEntry and onExit according state hierarchy
- Object oex[] = onExit.toArray();
- onExit.clear();
- Object oen[] = onEntry.toArray();
- onEntry.clear();
- Arrays.sort(oex, getTTComparator());
- Arrays.sort(oen, getTTComparator());
- step.getExitList().addAll(Arrays.asList(oex));
- // we need to impose reverse order for the onEntry list
- List entering = Arrays.asList(oen);
- Collections.reverse(entering);
- step.getEntryList().addAll(entering);
- // reset 'done' flag
- for (Iterator reset = entering.iterator(); reset.hasNext(); ) {
- Object o = reset.next();
- if(o instanceof State) {
- ((State)o).setDone(false);
- }
- }
- }
-
- /**
- * Go over the exit list and update history information for relevant states.
- *
- * @param step
- * [inout]
- * @param errRep
- * ErrorReporter callback [inout]
- */
- public void updateHistoryStates(Step step, ErrorReporter errRep) {
- Set oldState = step.getBeforeStatus().getStates();
- for (Iterator i = step.getExitList().iterator(); i.hasNext(); ) {
- Object o = i.next();
- if (o instanceof State) {
- State s = (State) o;
- if (s.hasHistory()) {
- Set shallow = null;
- Set deep = null;
- Iterator j = s.getHistory().iterator();
- while (j.hasNext()) {
- History h = (History) j.next();
- if (h.isDeep()) {
- if (deep == null) {
- //calculate deep history for a given state once
- deep = new HashSet();
- Iterator k = oldState.iterator();
- while (k.hasNext()) {
- State os = (State) k.next();
- if (SCXMLHelper.isDescendant(os, s)) {
- deep.add(os);
- }
- }
- }
- h.setLastConfiguration(deep);
- } else {
- if (shallow == null) {
- //calculate shallow history for a given state
- // once
- shallow = new HashSet();
- shallow.addAll(s.getChildren().values());
- shallow.retainAll(SCXMLHelper
- .getAncestorClosure(oldState, null));
- }
- h.setLastConfiguration(shallow);
- }
- }
- shallow = null;
- deep = null;
- }
- }
- }
- }
-
- /**
- * Implements prefix match, that is, if, for example,
- * "mouse.click" is a member of eventOccurrences and a
- * transition is triggered by "mouse", the method returns true.
- *
- * @param transEvent
- * a trigger event of a transition
- * @param eventOccurrences
- * current events
- * @return true/false
- */
- public boolean eventMatch(String transEvent, Set eventOccurrences) {
- if (SCXMLHelper.isStringEmpty(transEvent)) {
- return true;
- } else {
- String transEventDot = transEvent + "."; //wildcard (prefix) event
- // support
- Iterator i = eventOccurrences.iterator();
- while (i.hasNext()) {
- String evt = (String) i.next();
- if (evt.equals(transEvent) || evt.startsWith(transEventDot)) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * TransitionTargetComparator factory method
- */
- final Comparator getTTComparator() {
- return ttc;
- }
+ /**
+ * @param input
+ * SCXML state machine
+ * @return normalized SCXML state machine, pseudo states are removed, etc.
+ * @param errRep
+ * ErrorReporter callback
+ */
+ public SCXML normalizeStateMachine(SCXML input, ErrorReporter errRep) {
+ //it is a no-op for now
+ return input;
+ }
+
+ /**
+ * @param input
+ * SCXML state machine [in]
+ * @param states
+ * a set of States to populate [out]
+ * @param entryList
+ * a list of States and Parallels to enter [out]
+ * @param errRep
+ * ErrorReporter callback [inout]
+ * @throws ModelException
+ * in case there is a fatal SCXML object model problem.
+ */
+ public void determineInitialStates(SCXML input, Set states, List entryList,
+ ErrorReporter errRep) throws ModelException {
+ State tmp = input.getInitialState();
+ if (tmp == null) {
+ errRep.onError(ErrorReporter.NO_INITIAL,
+ "SCXML initialstate is missing!", input);
+ } else {
+ states.add(tmp);
+ determineTargetStates(states, errRep);
+ //set of ALL entered states (even if initialState is a jump-over)
+ Set onEntry = SCXMLHelper.getAncestorClosure(states, null);
+ // sort onEntry according state hierarchy
+ Object oen[] = onEntry.toArray();
+ onEntry.clear();
+ Arrays.sort(oen, getTTComparator());
+ // we need to impose reverse order for the onEntry list
+ List entering = Arrays.asList(oen);
+ Collections.reverse(entering);
+ entryList.addAll(entering);
+
+ }
+ }
+
+ /**
+ * @param actions
+ * a list of actions to execute [in]
+ * @param derivedEvents
+ * collection of internal events generated by the actions [out]
+ * @param exec
+ * execution environment [inout]
+ * @throws ModelException
+ * in case there is a fatal SCXML object model problem.
+ * @throws SCXMLExpressionException
+ * @see ErrorReporter
+ * @see NotificationRegistry
+ * @see EventDispatcher
+ * @see Context
+ * @see Evaluator
+ */
+ public void executeActionList(List actions, Collection derivedEvents,
+ SCXMLExecutor exec, ErrorReporter errRep) throws ModelException,
+ SCXMLExpressionException {
+ // NOTE: "if" statement is a container - we may need to call this method
+ // recursively and pass a sub-list of actions embedded in a particular
+ // "if"
+ Evaluator eval = exec.getEvaluator();
+ for (Iterator i = actions.iterator(); i.hasNext(); ) {
+ Action a = (Action) i.next();
+ State parentState = a.getParentState();
+ Context ctx = parentState.getContext();
+ // NOTE: "elseif" and "else" do not appear here, since they are
+ // always handled as a part of "if" as a container
+ if (a instanceof Assign) {
+ Assign asgn = (Assign) a;
+ String varName = asgn.getName();
+ if (!ctx.has(varName)) {
+ errRep.onError(ErrorReporter.UNDEFINED_VARIABLE, varName
+ + " = null", parentState);
+ } else {
+ Object varObj = eval.eval(ctx, asgn.getExpr());
+ ctx.set(varName, varObj);
+ TriggerEvent ev = new TriggerEvent(varName + ".change",
+ TriggerEvent.CHANGE_EVENT);
+ derivedEvents.add(ev);
+ }
+ } else if (a instanceof Cancel) {
+ Cancel cncl = (Cancel) a;
+ exec.getEventdispatcher().cancel(cncl.getSendId());
+ } else if (a instanceof Exit) {
+ // Ignore; Exit instance holds other information that might
+ // be needed, and is not transformed at parse time.
+ //throw new ModelException("The <exit/> tag must be transformed"
+ // + " to an anonymous final state at the parse time!");
+ } else if (a instanceof If) {
+ //determine elseif/else separators evaluate conditions
+ //extract a sub-list of If's actions and invoke
+ // executeActionList()
+ List todoList = new LinkedList();
+ If ifo = (If) a;
+ List subAct = ifo.getActions();
+ boolean cnd = eval.evalCond(ctx, ifo.getCond()).booleanValue();
+ for (Iterator ifiter = subAct.iterator(); ifiter.hasNext(); ) {
+ Action aa = (Action) ifiter.next();
+ if (cnd && !(aa instanceof ElseIf) && !(aa instanceof Else)) {
+ todoList.add(aa);
+ } else if (cnd
+ && (aa instanceof ElseIf || aa instanceof Else)) {
+ break;
+ } else if (aa instanceof ElseIf) {
+ cnd = eval.evalCond(ctx, ((ElseIf) aa).getCond())
+ .booleanValue();
+ } else if (aa instanceof Else) {
+ cnd = true;
+ } else {
+ //skip
+ }
+ }
+ if (!todoList.isEmpty()) {
+ executeActionList(todoList, derivedEvents, exec, errRep);
+ }
+ todoList.clear();
+ } else if (a instanceof Log) {
+ Log lg = (Log) a;
+ Object exprRslt = eval.eval(ctx, lg.getExpr());
+ appLog.info(lg.getLabel() + ": " + String.valueOf(exprRslt));
+ } else if (a instanceof Send) {
+ Send snd = (Send) a;
+ Object hints = null;
+ if (!SCXMLHelper.isStringEmpty(snd.getHints())) {
+ hints = eval.eval(ctx, snd.getHints());
+ }
+ Map params = null;
+ if (!SCXMLHelper.isStringEmpty(snd.getNamelist())) {
+ StringTokenizer tkn = new StringTokenizer(snd.getNamelist());
+ params = new HashMap(tkn.countTokens());
+ while (tkn.hasMoreTokens()) {
+ String varName = tkn.nextToken();
+ Object varObj = ctx.get(varName);
+ if (varObj == null) {
+ //considered as a warning here
+ errRep.onError(ErrorReporter.UNDEFINED_VARIABLE,
+ varName + " = null", parentState);
+ }
+ params.put(varName, varObj);
+ }
+ }
+ exec.getEventdispatcher().send(snd.getSendId(),
+ snd.getTarget(), snd.getTargetType(), snd.getEvent(),
+ params, hints, Long.parseLong(snd.getDelay()));
+ } else if (a instanceof Var) {
+ Var vr = (Var) a;
+ String varName = vr.getName();
+ Object varObj = eval.eval(ctx, vr.getExpr());
+ ctx.setLocal(varName, varObj);
+ TriggerEvent ev = new TriggerEvent(varName + ".change",
+ TriggerEvent.CHANGE_EVENT);
+ derivedEvents.add(ev);
+ } else {
+ errRep.onError(ErrorReporter.UNKNOWN_ACTION,
+ "unsupported executable statement", a);
+ }
+ }
+ }
+
+ /**
+ * Exectutes all OnExit/Transition/OnEntry transitional actions.
+ *
+ * @param step
+ * [inout] provides EntryList, TransitList, ExitList gets updated
+ * its AfterStatus/Events
+ * @param exec
+ * [inout] execution environment - SCXMLExecutor instance
+ * @param errRep
+ * [out[ error reporter
+ * @throws ModelException
+ * in case there is a fatal SCXML object model problem.
+ */
+ public void executeActions(Step step, SCXMLExecutor exec,
+ ErrorReporter errRep) throws ModelException {
+ SCXML sm = exec.getStateMachine();
+ NotificationRegistry nr = sm.getNotificationRegistry();
+ Collection internalEvents = step.getAfterStatus().getEvents();
+ // ExecutePhaseActions / OnExit
+ for (Iterator i = step.getExitList().iterator(); i.hasNext(); ) {
+ TransitionTarget tt = (TransitionTarget) i.next();
+ OnExit oe = tt.getOnExit();
+ try {
+ executeActionList(oe.getActions(), internalEvents, exec, errRep);
+ } catch (SCXMLExpressionException e) {
+ errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
+ oe);
+ }
+ nr.fireOnExit(tt, tt);
+ nr.fireOnExit(sm, tt);
+ TriggerEvent te = new TriggerEvent(tt.getId() + ".exit",
+ TriggerEvent.CHANGE_EVENT);
+ internalEvents.add(te);
+ }
+ // ExecutePhaseActions / Transitions
+ for (Iterator i = step.getTransitList().iterator(); i.hasNext(); ) {
+ Transition t = (Transition) i.next();
+ try {
+ executeActionList(t.getActions(), internalEvents, exec, errRep);
+ } catch (SCXMLExpressionException e) {
+ errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
+ t);
+ }
+ nr.fireOnTransition(t, t.getParent(), t.getRuntimeTarget(), t);
+ nr.fireOnTransition(sm, t.getParent(), t.getRuntimeTarget(), t);
+ }
+ // ExecutePhaseActions / OnEntry
+ for (Iterator i = step.getEntryList().iterator(); i.hasNext(); ) {
+ TransitionTarget tt = (TransitionTarget) i.next();
+ OnEntry oe = tt.getOnEntry();
+ try {
+ executeActionList(oe.getActions(), internalEvents, exec, errRep);
+ } catch (SCXMLExpressionException e) {
+ errRep.onError(ErrorReporter.EXPRESSION_ERROR, e.getMessage(),
+ oe);
+ }
+ nr.fireOnEntry(tt, tt);
+ nr.fireOnEntry(sm, tt);
+ TriggerEvent te = new TriggerEvent(tt.getId() + ".entry",
+ TriggerEvent.CHANGE_EVENT);
+ internalEvents.add(te);
+ //3.2.1 and 3.4 (.done events)
+ if (tt instanceof State) {
+ State ts = (State)tt;
+ if (ts.getIsFinal()) {
+ State parent = (State)ts.getParent();
+ String prefix = (parent == null) ? "" : parent.getId();
+ te = new TriggerEvent(prefix + ".done",
+ TriggerEvent.CHANGE_EVENT);
+ internalEvents.add(te);
+ if (parent != null) {
+ parent.setDone(true);
+ }
+ if (parent != null && parent.isRegion()) {
+ //3.4 we got a region, which is finalized
+ //let's check its siblings too
+ Parallel p = (Parallel)parent.getParent();
+ int finCount = 0;
+ int pCount = p.getStates().size();
+ Iterator regions = p.getStates().iterator();
+ while(regions.hasNext()) {
+ State reg = (State)regions.next();
+ if(reg.isDone()) {
+ finCount++;
+ }
+ }
+ if(finCount == pCount) {
+ te = new TriggerEvent(p.getId() + ".done",
+ TriggerEvent.CHANGE_EVENT);
+ internalEvents.add(te);
+ te = new TriggerEvent(p.getParent().getId() + ".done",
+ TriggerEvent.CHANGE_EVENT);
+ internalEvents.add(te);
+ //this is not in the specs, but is makes sense
+ p.getParentState().setDone(true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param stateMachine
+ * a SM to traverse [in]
+ * @param step
+ * with current status and list of transitions to populate
+ * [inout]
+ * @param errRep
+ * ErrorReporter callback [inout]
+ */
+ public void enumerateReachableTransitions(SCXML stateMachine, Step step,
+ ErrorReporter errRep) {
+ // prevents adding the same transition multiple times
+ Set transSet = new HashSet();
+ // prevents visiting the same state multiple times
+ Set stateSet = new HashSet(step.getBeforeStatus().getStates());
+ // breath-first search to-do list
+ LinkedList todoList = new LinkedList(stateSet);
+ while (!todoList.isEmpty()) {
+ State st = (State) todoList.removeFirst();
+ for (Iterator i = st.getTransitionsList().iterator(); i.hasNext(); ) {
+ Transition t = (Transition) i.next();
+ if (!transSet.contains(t)) {
+ transSet.add(t);
+ step.getTransitList().add(t);
+ }
+ }
+ State parent = st.getParentState();
+ if (parent != null && !stateSet.contains(parent)) {
+ stateSet.add(parent);
+ todoList.addLast(parent);
+ }
+ }
+ transSet.clear();
+ stateSet.clear();
+ todoList.clear();
+ }
+
+ /**
+ * @param step
+ * [inout]
+ * @param evaluator
+ * guard condition evaluator
+ * @param errRep
+ * ErrorReporter callback [inout]
+ */
+ public void filterTransitionsSet(Step step, Evaluator evaluator,
+ ErrorReporter errRep) {
+ /*
+ * - filter transition set by applying events (step/beforeStatus/events +
+ * step/externalEvents) (local check) - evaluating guard conditions for
+ * each transition (local check) - transition precedence (bottom-up) as
+ * defined by SCXML specs
+ */
+ Set allEvents = new HashSet(step.getBeforeStatus().getEvents()
+ .size()
+ + step.getExternalEvents().size());
+ //for now, we only match against event names
+ for (Iterator ei = step.getBeforeStatus().getEvents().iterator();
+ ei.hasNext(); ) {
+ TriggerEvent te = (TriggerEvent) ei.next();
+ allEvents.add(te.getName());
+ }
+ for (Iterator ei = step.getExternalEvents().iterator(); ei.hasNext(); ) {
+ TriggerEvent te = (TriggerEvent) ei.next();
+ allEvents.add(te.getName());
+ }
+ //remove list (filtered-out list)
+ List removeList = new LinkedList();
+ //iterate over non-filtered transition set
+ for (Iterator iter = step.getTransitList().iterator(); iter.hasNext();) {
+ Transition t = (Transition) iter.next();
+ // event check
+ String event = t.getEvent();
+ if (!eventMatch(event, allEvents)) {
+ // t has a non-empty event which is not triggered
+ removeList.add(t);
+ continue; //makes no sense to eval guard cond.
+ }
+ // guard condition check
+ Boolean rslt;
+ String expr = t.getCond();
+ if (SCXMLHelper.isStringEmpty(expr)) {
+ rslt = Boolean.TRUE;
+ } else {
+ try {
+ rslt = evaluator.evalCond(((State) t.getParent())
+ .getContext(), t.getCond());
+ } catch (SCXMLExpressionException e) {
+ rslt = Boolean.FALSE;
+ errRep.onError(ErrorReporter.EXPRESSION_ERROR, e
+ .getMessage(), t);
+ }
+ }
+ if (rslt.booleanValue() == false) {
+ // guard condition has not passed
+ removeList.add(t);
+ }
+ }
+ // apply event + guard condition filter
+ step.getTransitList().removeAll(removeList);
+ // cleanup temporary structures
+ allEvents.clear();
+ removeList.clear();
+ // optimization - global precedence potentially applies
+ // only if there are multiple enabled transitions
+ if (step.getTransitList().size() > 1) {
+ // global transition precedence check
+ Object trans[] = step.getTransitList().toArray();
+ Set currentStates = step.getBeforeStatus().getStates();
+ // non-determinism candidates
+ Set nonDeterm = new HashSet();
+ for (int i = 0; i < trans.length; i++) {
+ Transition t = (Transition) trans[i];
+ TransitionTarget tsrc = t.getParent();
+ for (int j = i + 1; j < trans.length; j++) {
+ Transition t2 = (Transition) trans[j];
+ boolean conflict = SCXMLHelper.inConflict(t, t2,
+ currentStates);
+ if (conflict) {
+ //potentially conflicting transitions
+ TransitionTarget t2src = t2.getParent();
+ if (SCXMLHelper.isDescendant(t2src, tsrc)) {
+ //t2 takes precedence over t
+ removeList.add(t);
+ break; //it makes no sense to waste cycles with t
+ } else if (SCXMLHelper.isDescendant(tsrc, t2src)) {
+ //t takes precendence over t2
+ removeList.add(t2);
+ } else {
+ //add both to the non-determinism candidates
+ nonDeterm.add(t);
+ nonDeterm.add(t2);
+ }
+ }
+ }
+ }
+ // check if all non-deterministic situations have been resolved
+ nonDeterm.removeAll(removeList);
+ if (nonDeterm.size() > 0) {
+ errRep.onError(ErrorReporter.NON_DETERMINISTIC,
+ "Multiple conflicting transitions enabled.", nonDeterm);
+ }
+ // apply global transition filter
+ step.getTransitList().removeAll(removeList);
+ removeList.clear();
+ nonDeterm.clear();
+ }
+ }
+
+ /**
+ * @param step
+ * transitional step
+ * @param errRep
+ * ErrorReporter callback [inout]
+ */
+ public void seedTargetSet(Step step, ErrorReporter errRep) {
+ Set sources = step.getBeforeStatus().getStates();
+ Set targets = step.getAfterStatus().getStates();
+ List transitions = step.getTransitList();
+ /* populate the target set by taking targets of selected transitions */
+ for (Iterator i = transitions.iterator(); i.hasNext(); ) {
+ Transition t = (Transition) i.next();
+ targets.add(t.getRuntimeTarget());
+ }
+ /* retain the source states, which are not affected by the transitions */
+ for (Iterator i = sources.iterator(); i.hasNext(); ) {
+ State s = (State) i.next();
+ boolean retain = true;
+ for (Iterator j = transitions.iterator(); j.hasNext(); ) {
+ Transition t = (Transition) j.next();
+ State ts = (State) t.getParent();
+ if (s == ts || SCXMLHelper.isDescendant(s, ts)) {
+ retain = false;
+ break;
+ }
+ }
+ if (retain) {
+ targets.add(s);
+ }
+ }
+ }
+
+ /**
+ * @param states
+ * a set seeded in previous step [inout]
+ * @param errRep
+ * ErrorReporter callback [inout]
+ * @see #seedTargetSet(Step, ErrorReporter)
+ */
+ public void determineTargetStates(Set states, ErrorReporter errRep)
+ throws ModelException {
+ LinkedList wrkSet = new LinkedList(states);
+ // clear the seed-set - will be populated by leaf states
+ states.clear();
+ while (!wrkSet.isEmpty()) {
+ TransitionTarget tt = (TransitionTarget) wrkSet.removeFirst();
+ if (tt instanceof State) {
+ State st = (State) tt;
+ //state can either have parallel or substates w. initial
+ //or it is a leaf state
+ // NOTE: Digester has to verify this precondition!
+ if (st.isSimple()) {
+ states.add(st); //leaf
+ } else if (st.isOrthogonal()) {
+ wrkSet.addLast(st.getParallel()); //parallel
+ } else {
+ // composite state
+ Initial ini = st.getInitial();
+ if (ini == null) {
+ errRep.onError(ErrorReporter.NO_INITIAL,
+ "Initial pseudostate is missing!", st);
+ }
+ // If we are here, transition target must be a State
+ // or History
+ TransitionTarget init = ini.getTransition().getTarget();
+ if (init == null
+ || !(init instanceof State || init instanceof History)) {
+ errRep.onError(ErrorReporter.ILLEGAL_INITIAL,
+ "Initial does not point to a State or a History!",
+ st);
+ } else {
+ wrkSet.addLast(init);
+ }
+ }
+ } else if (tt instanceof Parallel) {
+ Parallel prl = (Parallel) tt;
+ Iterator i = prl.getStates().iterator();
+ while (i.hasNext()) {
+ //fork
+ wrkSet.addLast(i.next());
+ }
+ } else if (tt instanceof History) {
+ History h = (History) tt;
+ if (h.isEmpty()) {
+ wrkSet.addLast(h.getTransition().getRuntimeTarget());
+ } else {
+ wrkSet.addAll(h.getLastConfiguration());
+ }
+ } else {
+ throw new ModelException("Unknown TransitionTarget subclass:"
+ + tt.getClass().getName());
+ }
+ }
+ if (!SCXMLHelper.isLegalConfig(states, errRep)) {
+ throw new ModelException("Illegal state machine configuration!");
+ }
+ }
+
+ /**
+ * @param step
+ * [inout]
+ * @param errRep
+ * ErrorReporter callback [inout]
+ */
+ public void buildOnExitOnEntryLists(Step step, ErrorReporter errRep) {
+ //set of exited states
+ Set onExit = SCXMLHelper.getAncestorClosure(step.getBeforeStatus()
+ .getStates(), null);
+ Set onExit2 = new HashSet(onExit);
+ //set of entered states
+ Set onEntry = SCXMLHelper.getAncestorClosure(step.getAfterStatus()
+ .getStates(), null);
+ //remove common sub-set
+ onExit.removeAll(onEntry);
+ onEntry.removeAll(onExit2);
+ //explicitly add self-transitions
+ for (Iterator i = step.getTransitList().iterator(); i.hasNext(); ) {
+ Transition t = (Transition) i.next();
+ if (t.getParent() == t.getTarget()) {
+ onExit.add(t.getParent());
+ onEntry.add(t.getTarget());
+ }
+ }
+ // sort onEntry and onExit according state hierarchy
+ Object oex[] = onExit.toArray();
+ onExit.clear();
+ Object oen[] = onEntry.toArray();
+ onEntry.clear();
+ Arrays.sort(oex, getTTComparator());
+ Arrays.sort(oen, getTTComparator());
+ step.getExitList().addAll(Arrays.asList(oex));
+ // we need to impose reverse order for the onEntry list
+ List entering = Arrays.asList(oen);
+ Collections.reverse(entering);
+ step.getEntryList().addAll(entering);
+ // reset 'done' flag
+ for (Iterator reset = entering.iterator(); reset.hasNext(); ) {
+ Object o = reset.next();
+ if(o instanceof State) {
+ ((State)o).setDone(false);
+ }
+ }
+ }
+
+ /**
+ * Go over the exit list and update history information for relevant states.
+ *
+ * @param step
+ * [inout]
+ * @param errRep
+ * ErrorReporter callback [inout]
+ */
+ public void updateHistoryStates(Step step, ErrorReporter errRep) {
+ Set oldState = step.getBeforeStatus().getStates();
+ for (Iterator i = step.getExitList().iterator(); i.hasNext(); ) {
+ Object o = i.next();
+ if (o instanceof State) {
+ State s = (State) o;
+ if (s.hasHistory()) {
+ Set shallow = null;
+ Set deep = null;
+ Iterator j = s.getHistory().iterator();
+ while (j.hasNext()) {
+ History h = (History) j.next();
+ if (h.isDeep()) {
+ if (deep == null) {
+ //calculate deep history for a given state once
+ deep = new HashSet();
+ Iterator k = oldState.iterator();
+ while (k.hasNext()) {
+ State os = (State) k.next();
+ if (SCXMLHelper.isDescendant(os, s)) {
+ deep.add(os);
+ }
+ }
+ }
+ h.setLastConfiguration(deep);
+ } else {
+ if (shallow == null) {
+ //calculate shallow history for a given state
+ // once
+ shallow = new HashSet();
+ shallow.addAll(s.getChildren().values());
+ shallow.retainAll(SCXMLHelper
+ .getAncestorClosure(oldState, null));
+ }
+ h.setLastConfiguration(shallow);
+ }
+ }
+ shallow = null;
+ deep = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Implements prefix match, that is, if, for example,
+ * "mouse.click" is a member of eventOccurrences and a
+ * transition is triggered by "mouse", the method returns true.
+ *
+ * @param transEvent
+ * a trigger event of a transition
+ * @param eventOccurrences
+ * current events
+ * @return true/false
+ */
+ public boolean eventMatch(String transEvent, Set eventOccurrences) {
+ if (SCXMLHelper.isStringEmpty(transEvent)) {
+ return true;
+ } else {
+ String transEventDot = transEvent + "."; //wildcard (prefix) event
+ // support
+ Iterator i = eventOccurrences.iterator();
+ while (i.hasNext()) {
+ String evt = (String) i.next();
+ if (evt.equals(transEvent) || evt.startsWith(transEventDot)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * TransitionTargetComparator factory method
+ */
+ final Comparator getTTComparator() {
+ return ttc;
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Status.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Status.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Status.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Status.java Wed Aug 10 14:10:59 2005
@@ -32,79 +32,79 @@
* @author Rahul Akolkar
*/
public class Status {
-
- /**
- * The states that are currently active.
- */
- private Set states;
-
- /**
- * The events that are currently queued.
- */
- private Collection events;
-
- /**
- * Have we reached a final configuration for this state machine.
- *
- * True - if all the states are final and there are not events
- * pending from the last step. False - otherwise.
- *
- * @return Whether a final configuration has been reached.
- */
- public boolean isFinal() {
- boolean rslt = true;
- for (Iterator i = states.iterator(); i.hasNext(); ) {
- State s = (State)i.next();
- if (!s.getIsFinal()) {
- rslt = false;
- break;
- }
- //the status is final only iff these are top-level states
- if(s.getParent() != null) {
- rslt = false;
- break;
- }
- }
- if (!events.isEmpty()) {
- rslt = false;
- }
- return rslt;
- }
-
- /**
- * Constructor
- */
- public Status() {
- states = new HashSet();
- events = new ArrayList();
- }
-
- /**
- * Get the states configuration (leaf only).
- *
- * @return Returns the states configuration - simple (leaf) states only.
- */
- public Set getStates() {
- return states;
- }
-
- /**
- * Get the events that are currently queued.
- *
- * @return The events that are currently queued.
- */
- public Collection getEvents() {
- return events;
- }
-
- /**
- * Get the complete states configuration
- *
- * @return complete states configuration including simple states and their
- * complex ancestors up to the root.
- */
- public Set getAllStates() {
- return SCXMLHelper.getAncestorClosure(states, null);
- }
-
+
+ /**
+ * The states that are currently active.
+ */
+ private Set states;
+
+ /**
+ * The events that are currently queued.
+ */
+ private Collection events;
+
+ /**
+ * Have we reached a final configuration for this state machine.
+ *
+ * True - if all the states are final and there are not events
+ * pending from the last step. False - otherwise.
+ *
+ * @return Whether a final configuration has been reached.
+ */
+ public boolean isFinal() {
+ boolean rslt = true;
+ for (Iterator i = states.iterator(); i.hasNext(); ) {
+ State s = (State)i.next();
+ if (!s.getIsFinal()) {
+ rslt = false;
+ break;
+ }
+ //the status is final only iff these are top-level states
+ if(s.getParent() != null) {
+ rslt = false;
+ break;
+ }
+ }
+ if (!events.isEmpty()) {
+ rslt = false;
+ }
+ return rslt;
+ }
+
+ /**
+ * Constructor
+ */
+ public Status() {
+ states = new HashSet();
+ events = new ArrayList();
+ }
+
+ /**
+ * Get the states configuration (leaf only).
+ *
+ * @return Returns the states configuration - simple (leaf) states only.
+ */
+ public Set getStates() {
+ return states;
+ }
+
+ /**
+ * Get the events that are currently queued.
+ *
+ * @return The events that are currently queued.
+ */
+ public Collection getEvents() {
+ return events;
+ }
+
+ /**
+ * Get the complete states configuration
+ *
+ * @return complete states configuration including simple states and their
+ * complex ancestors up to the root.
+ */
+ public Set getAllStates() {
+ return SCXMLHelper.getAncestorClosure(states, null);
+ }
+
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Step.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Step.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Step.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/Step.java Wed Aug 10 14:10:59 2005
@@ -28,125 +28,125 @@
* @author Rahul Akolkar
*/
class Step {
-
- /**
- * Constructor
- */
- public Step() {
- this.externalEvents = new ArrayList();
- this.beforeStatus = new Status();
- this.afterStatus = new Status();
- this.exitList = new ArrayList();
- this.entryList = new ArrayList();
- this.transitList = new ArrayList();
- }
-
- /**
- * @param externalEvents The external events received in this
- * unit of progression
- * @param beforeStatus The before status
- */
- public Step(Collection externalEvents, Status beforeStatus) {
- if(externalEvents != null) {
- this.externalEvents = externalEvents;
- } else {
- this.externalEvents = new ArrayList();
- }
- if(beforeStatus != null) {
- this.beforeStatus = beforeStatus;
- } else {
- this.beforeStatus = new Status();
- }
- this.afterStatus = new Status();
- this.exitList = new ArrayList();
- this.entryList = new ArrayList();
- this.transitList = new ArrayList();
- }
-
- /**
- * The external events in this step
- */
- private Collection externalEvents;
+
+ /**
+ * Constructor
+ */
+ public Step() {
+ this.externalEvents = new ArrayList();
+ this.beforeStatus = new Status();
+ this.afterStatus = new Status();
+ this.exitList = new ArrayList();
+ this.entryList = new ArrayList();
+ this.transitList = new ArrayList();
+ }
+
+ /**
+ * @param externalEvents The external events received in this
+ * unit of progression
+ * @param beforeStatus The before status
+ */
+ public Step(Collection externalEvents, Status beforeStatus) {
+ if(externalEvents != null) {
+ this.externalEvents = externalEvents;
+ } else {
+ this.externalEvents = new ArrayList();
+ }
+ if(beforeStatus != null) {
+ this.beforeStatus = beforeStatus;
+ } else {
+ this.beforeStatus = new Status();
+ }
+ this.afterStatus = new Status();
+ this.exitList = new ArrayList();
+ this.entryList = new ArrayList();
+ this.transitList = new ArrayList();
+ }
+
+ /**
+ * The external events in this step
+ */
+ private Collection externalEvents;
- /**
- * The status before this step
- */
- private Status beforeStatus;
+ /**
+ * The status before this step
+ */
+ private Status beforeStatus;
- /**
- * The status after this step
- */
- private Status afterStatus;
+ /**
+ * The status after this step
+ */
+ private Status afterStatus;
- /**
- * The list of TransitionTargets that were exited during this step
+ /**
+ * The list of TransitionTargets that were exited during this step
*/
- private List exitList;
+ private List exitList;
- /**
- * The list of TransitionTargets that were entered during this step
- */
- private List entryList;
+ /**
+ * The list of TransitionTargets that were entered during this step
+ */
+ private List entryList;
- /**
- * The list of Transitions taken during this step
- */
- private List transitList;
-
- /**
- * @return Returns the afterStatus.
- */
- public Status getAfterStatus() {
- return afterStatus;
- }
-
- /**
- * @param afterStatus The afterStatus to set.
- */
- public void setAfterStatus(Status afterStatus) {
- this.afterStatus = afterStatus;
- }
-
- /**
- * @return Returns the beforeStatus.
- */
- public Status getBeforeStatus() {
- return beforeStatus;
- }
-
- /**
- * @param beforeStatus The beforeStatus to set.
- */
- public void setBeforeStatus(Status beforeStatus) {
- this.beforeStatus = beforeStatus;
- }
-
- /**
- * @return Returns the entryList.
- */
- public List getEntryList() {
- return entryList;
- }
-
- /**
- * @return Returns the exitList.
- */
- public List getExitList() {
- return exitList;
- }
-
- /**
- * @return Returns the externalEvents.
- */
- public Collection getExternalEvents() {
- return externalEvents;
- }
-
- /**
- * @return Returns the transitList.
- */
- public List getTransitList() {
- return transitList;
- }
+ /**
+ * The list of Transitions taken during this step
+ */
+ private List transitList;
+
+ /**
+ * @return Returns the afterStatus.
+ */
+ public Status getAfterStatus() {
+ return afterStatus;
+ }
+
+ /**
+ * @param afterStatus The afterStatus to set.
+ */
+ public void setAfterStatus(Status afterStatus) {
+ this.afterStatus = afterStatus;
+ }
+
+ /**
+ * @return Returns the beforeStatus.
+ */
+ public Status getBeforeStatus() {
+ return beforeStatus;
+ }
+
+ /**
+ * @param beforeStatus The beforeStatus to set.
+ */
+ public void setBeforeStatus(Status beforeStatus) {
+ this.beforeStatus = beforeStatus;
+ }
+
+ /**
+ * @return Returns the entryList.
+ */
+ public List getEntryList() {
+ return entryList;
+ }
+
+ /**
+ * @return Returns the exitList.
+ */
+ public List getExitList() {
+ return exitList;
+ }
+
+ /**
+ * @return Returns the externalEvents.
+ */
+ public Collection getExternalEvents() {
+ return externalEvents;
+ }
+
+ /**
+ * @return Returns the transitList.
+ */
+ public List getTransitList() {
+ return transitList;
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TransitionTargetComparator.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TransitionTargetComparator.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TransitionTargetComparator.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TransitionTargetComparator.java Wed Aug 10 14:10:59 2005
@@ -29,47 +29,47 @@
*/
class TransitionTargetComparator implements Comparator {
- /**
- * Constructor
- */
- TransitionTargetComparator() {
- super();
- }
+ /**
+ * Constructor
+ */
+ TransitionTargetComparator() {
+ super();
+ }
- /**
- * Compares two instances of TransitionTarget in terms of the SCXML tree hierarchy.
- * <p>Important Remarks:</p> does not fullfill the Comparator contract, since
- * it returns 0 if o1 == o2 and also if they are not related to each other
- * and at the same time the chain-to-parent length for o1 is the same length
- * as for o2 (that is, they are equally deeply nested)
- * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
- * @throws ClassCastException
- * if any of the parameters is not a TransitionTarget intance.
- * @see TransitionTarget
- */
- public final int compare(Object o1, Object o2) {
- TransitionTarget tt1 = (TransitionTarget)o1;
- TransitionTarget tt2 = (TransitionTarget)o2;
- if(tt1 == tt2) {
- return 0;
- } else if(SCXMLHelper.isDescendant(tt1, tt2)) {
- return -1;
- } else if(SCXMLHelper.isDescendant(tt2, tt1)) {
- return 1;
- } else {
- //the tt1 and tt2 are parallel, now we have to count chain sizes
- int tc1 = countChainLength(tt1);
- int tc2 = countChainLength(tt2);
- //longer the chain, deeper the node is
- return tc2 - tc1;
- }
- }
-
- private final int countChainLength(TransitionTarget tt) {
- int count = 0;
- while((tt = tt.getParent()) != null) {
- count++;
- }
- return count;
- }
+ /**
+ * Compares two instances of TransitionTarget in terms of the SCXML tree hierarchy.
+ * <p>Important Remarks:</p> does not fullfill the Comparator contract, since
+ * it returns 0 if o1 == o2 and also if they are not related to each other
+ * and at the same time the chain-to-parent length for o1 is the same length
+ * as for o2 (that is, they are equally deeply nested)
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ * @throws ClassCastException
+ * if any of the parameters is not a TransitionTarget intance.
+ * @see TransitionTarget
+ */
+ public final int compare(Object o1, Object o2) {
+ TransitionTarget tt1 = (TransitionTarget)o1;
+ TransitionTarget tt2 = (TransitionTarget)o2;
+ if(tt1 == tt2) {
+ return 0;
+ } else if(SCXMLHelper.isDescendant(tt1, tt2)) {
+ return -1;
+ } else if(SCXMLHelper.isDescendant(tt2, tt1)) {
+ return 1;
+ } else {
+ //the tt1 and tt2 are parallel, now we have to count chain sizes
+ int tc1 = countChainLength(tt1);
+ int tc2 = countChainLength(tt2);
+ //longer the chain, deeper the node is
+ return tc2 - tc1;
+ }
+ }
+
+ private final int countChainLength(TransitionTarget tt) {
+ int count = 0;
+ while((tt = tt.getParent()) != null) {
+ count++;
+ }
+ return count;
+ }
}
Modified: jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TriggerEvent.java
URL: http://svn.apache.org/viewcvs/jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TriggerEvent.java?rev=231329&r1=231328&r2=231329&view=diff
==============================================================================
--- jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TriggerEvent.java (original)
+++ jakarta/taglibs/proper/rdc/trunk/src/org/apache/taglibs/rdc/scxml/TriggerEvent.java Wed Aug 10 14:10:59 2005
@@ -25,111 +25,111 @@
* @author Rahul Akolkar
*/
public class TriggerEvent {
-
- /**
- * Constructor
- *
- * @param name The event name
- * @param type The event type
- * @param payload The event payload
- */
- public TriggerEvent(String name, int type, Object payload) {
- super();
- this.name = name;
- this.type = type;
- this.payload = payload;
- }
-
- /**
- * Constructor
- *
- * @param name The event name
- * @param type The event type
- */
- public TriggerEvent(String name, int type) {
- this(name, type, null);
- }
-
- /**
- * <code>CALL_EVENT</code>
- */
- public static final int CALL_EVENT = 1;
-
- /**
- * <code>CHANGE_EVENT</code>
- *
- */
- public static final int CHANGE_EVENT = 2;
-
- /**
- * <code>SIGNAL_EVENT</code>
- *
- */
- public static final int SIGNAL_EVENT = 3;
-
- /**
- * <code>TIME_EVENT</code>
- *
- */
- public static final int TIME_EVENT = 4;
-
- /**
- * The event name
- *
- */
- private String name;
-
- /**
- * The event type
- *
- */
- private int type;
-
- /**
- * The event payload
- *
- */
- private Object payload;
-
- /**
- * @return Returns the name.
- */
- public String getName() {
- return name;
- }
-
- /**
- * @return Returns the payload.
- */
- public Object getPayload() {
- return payload;
- }
-
- /**
- * @return Returns the type.
- */
- public int getType() {
- return type;
- }
-
- /**
- * Define an equals operator for TriggerEvent
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object obj) {
- if (obj instanceof TriggerEvent) {
- TriggerEvent te2 = (TriggerEvent) obj;
- if (type == te2.type && name.equals(te2.name)
- && ((payload == null && te2.payload == null)
- || (payload != null && payload.equals(te2.payload)))) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-
+
+ /**
+ * Constructor
+ *
+ * @param name The event name
+ * @param type The event type
+ * @param payload The event payload
+ */
+ public TriggerEvent(String name, int type, Object payload) {
+ super();
+ this.name = name;
+ this.type = type;
+ this.payload = payload;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The event name
+ * @param type The event type
+ */
+ public TriggerEvent(String name, int type) {
+ this(name, type, null);
+ }
+
+ /**
+ * <code>CALL_EVENT</code>
+ */
+ public static final int CALL_EVENT = 1;
+
+ /**
+ * <code>CHANGE_EVENT</code>
+ *
+ */
+ public static final int CHANGE_EVENT = 2;
+
+ /**
+ * <code>SIGNAL_EVENT</code>
+ *
+ */
+ public static final int SIGNAL_EVENT = 3;
+
+ /**
+ * <code>TIME_EVENT</code>
+ *
+ */
+ public static final int TIME_EVENT = 4;
+
+ /**
+ * The event name
+ *
+ */
+ private String name;
+
+ /**
+ * The event type
+ *
+ */
+ private int type;
+
+ /**
+ * The event payload
+ *
+ */
+ private Object payload;
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return Returns the payload.
+ */
+ public Object getPayload() {
+ return payload;
+ }
+
+ /**
+ * @return Returns the type.
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Define an equals operator for TriggerEvent
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof TriggerEvent) {
+ TriggerEvent te2 = (TriggerEvent) obj;
+ if (type == te2.type && name.equals(te2.name)
+ && ((payload == null && te2.payload == null)
+ || (payload != null && payload.equals(te2.payload)))) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: taglibs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: taglibs-dev-help@jakarta.apache.org