[jbpm-commits] JBoss JBPM SVN: r6209 - in jbpm3/branches/jbpm-3.2-soa/modules/core/src: main/java/org/jbpm/graph/def and 8 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu Mar 4 08:17:11 EST 2010


Author: alex.guizar at jboss.com
Date: 2010-03-04 08:17:09 -0500 (Thu, 04 Mar 2010)
New Revision: 6209

Added:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/JBPM2784Test.java
Modified:
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Transition.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/el/impl/JbpmExpressionEvaluator.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/def/Task.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/jpdl/xml/jpdl-3.2.xsd
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/graph/node/JpdlDbTest.java
   jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/el/DecisionExpressionTest.java
Log:
JBPM-2784: accept condition attribute in transition element

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/context/exe/VariableContainer.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -155,34 +155,29 @@
 
     VariableInstance variableInstance = getVariableInstance(name);
     // if there is already a variable instance
-    // and it doesn't support the current value
+    // and it does not support the new value
     if (variableInstance != null && !variableInstance.supports(value)) {
       // delete the old variable instance
-      log.debug("variable type change, deleting '" + name + "' from "
-        + getToken());
+      log.debug(variableInstance.getToken() +  " unsets '" + name + "' due to type change");
       deleteVariableInstance(name);
       variableInstance = null;
     }
 
-    if (variableInstance == null) {
-      Token token = getToken();
-      log.debug("create variable '" + name + "' for " + token + " with value: "
-        + value);
-      variableInstance = VariableInstance.create(token, name, value);
-      addVariableInstance(variableInstance);
+    if (variableInstance != null) {
+      log.debug(variableInstance.getToken() + " sets '" + name + "' to " + value);
+      variableInstance.setValue(value);
     }
     else {
-      log.debug("update variable '" + name + "' for "
-        + variableInstance.getToken() + " to value: " + value);
-      variableInstance.setValue(value);
+      Token token = getToken();
+      log.debug(token + " initializes '" + name + "' to " + value);
+      addVariableInstance(VariableInstance.create(token, name, value));
     }
   }
 
   // local variable instances /////////////////////////////////////////////////
 
   public VariableInstance getVariableInstance(String name) {
-    return variableInstances != null ? (VariableInstance) variableInstances.get(name)
-        : null;
+    return variableInstances != null ? (VariableInstance) variableInstances.get(name) : null;
   }
 
   public Map getVariableInstances() {
@@ -200,8 +195,7 @@
 
   public void deleteVariableInstance(String name) {
     if (variableInstances != null) {
-      VariableInstance variableInstance =
-          (VariableInstance) variableInstances.remove(name);
+      VariableInstance variableInstance = (VariableInstance) variableInstances.remove(name);
       if (variableInstance != null) {
         getToken().addLog(new VariableDeleteLog(variableInstance));
         variableInstance.removeReferences();
@@ -228,8 +222,7 @@
     return null;
   }
 
-  public static Collection getUpdatedVariableContainers(
-      ProcessInstance processInstance) {
+  public static Collection getUpdatedVariableContainers(ProcessInstance processInstance) {
     return processInstance.getContextInstance().updatedVariableContainers;
   }
 

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Node.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -89,7 +89,7 @@
   };
 
   protected List leavingTransitions;
-  transient Map leavingTransitionMap;
+  private transient Map leavingTransitionMap;
   protected Set arrivingTransitions;
   protected Action action;
   protected SuperState superState;
@@ -108,15 +108,20 @@
   }
 
   // event types //////////////////////////////////////////////////////////////
+  
+  private static final String[] EVENT_TYPES = {
+    Event.EVENTTYPE_NODE_ENTER, Event.EVENTTYPE_NODE_LEAVE, Event.EVENTTYPE_BEFORE_SIGNAL,
+    Event.EVENTTYPE_AFTER_SIGNAL
+  };
 
-  public static final String[] supportedEventTypes =
-    { Event.EVENTTYPE_NODE_ENTER,
-      Event.EVENTTYPE_NODE_LEAVE,
-      Event.EVENTTYPE_BEFORE_SIGNAL,
-      Event.EVENTTYPE_AFTER_SIGNAL };
+  /**
+   * @deprecated arrays are mutable and thus vulnerable to external manipulation.
+   * use {@link #getSupportedEventTypes()} instead
+   */
+  public static final String[] supportedEventTypes = (String[]) EVENT_TYPES.clone();
 
   public String[] getSupportedEventTypes() {
-    return supportedEventTypes;
+    return (String[]) EVENT_TYPES.clone();
   }
 
   // constructors /////////////////////////////////////////////////////////////
@@ -163,8 +168,7 @@
     if (leavingTransitionMap == null && leavingTransitions != null) {
       // initialize the cached leaving transition map
       leavingTransitionMap = new HashMap();
-      ListIterator iter =
-        leavingTransitions.listIterator(leavingTransitions.size());
+      ListIterator iter = leavingTransitions.listIterator(leavingTransitions.size());
       while (iter.hasPrevious()) {
         Transition leavingTransition = (Transition) iter.previous();
         leavingTransitionMap.put(leavingTransition.getName(), leavingTransition);
@@ -200,8 +204,7 @@
     if (leavingTransition == null) {
       throw new IllegalArgumentException("leaving transition is null");
     }
-    if (leavingTransitions != null
-      && leavingTransitions.remove(leavingTransition)) {
+    if (leavingTransitions != null && leavingTransitions.remove(leavingTransition)) {
       leavingTransition.from = null;
       leavingTransitionMap = null;
     }
@@ -264,8 +267,8 @@
   boolean containsName(List leavingTransitions, String name) {
     for (Iterator iter = leavingTransitions.iterator(); iter.hasNext();) {
       Transition transition = (Transition) iter.next();
-      if (name != null ? name.equals(transition.getName())
-        : transition.getName() == null) return true;
+      if (name != null ? name.equals(transition.getName()) : transition.getName() == null)
+        return true;
     }
     return false;
   }
@@ -340,8 +343,7 @@
     if (arrivingTransition == null) {
       throw new IllegalArgumentException("arriving transition is null");
     }
-    if (arrivingTransitions != null
-      && arrivingTransitions.remove(arrivingTransition)) {
+    if (arrivingTransitions != null && arrivingTransitions.remove(arrivingTransition)) {
       arrivingTransition.to = null;
     }
   }
@@ -385,10 +387,7 @@
     // execute the node
     if (isAsync) {
       ExecuteNodeJob job = createAsyncContinuationJob(token);
-      executionContext.getJbpmContext()
-        .getServices()
-        .getMessageService()
-        .send(job);
+      executionContext.getJbpmContext().getServices().getMessageService().send(job);
       token.lock(job.toString());
     }
     else {
@@ -442,8 +441,7 @@
    */
   public void leave(ExecutionContext executionContext, String transitionName) {
     Transition transition = getLeavingTransition(transitionName);
-    if (transition == null)
-      throw new JbpmException("no such transition: " + transitionName);
+    if (transition == null) throw new JbpmException("no such transition: " + transitionName);
 
     leave(executionContext, transition);
   }
@@ -482,8 +480,7 @@
   // ///////////////////////////////////////////////////////////////////////////
 
   public ProcessDefinition getProcessDefinition() {
-    return superState != null ? superState.getProcessDefinition()
-      : processDefinition;
+    return superState != null ? superState.getProcessDefinition() : processDefinition;
   }
 
   // change the name of a node ////////////////////////////////////////////////
@@ -496,7 +493,7 @@
       if (superState != null) {
         if (superState.hasNode(name)) {
           throw new IllegalArgumentException("cannot rename " + this
-            + ", superstate already has a node named " + name);
+            + " because " + superState + " already has a node named " + name);
         }
         Map nodes = superState.getNodesMap();
         nodes.remove(oldName);
@@ -505,7 +502,7 @@
       else if (processDefinition != null) {
         if (processDefinition.hasNode(name)) {
           throw new IllegalArgumentException("cannot rename " + this
-            + ", process definition already has a node named " + name);
+            + " because " + processDefinition + " already has a node named " + name);
         }
         Map nodeMap = processDefinition.getNodesMap();
         nodeMap.remove(oldName);
@@ -523,8 +520,7 @@
    * the slash separated name that includes all the superstate names.
    */
   public String getFullyQualifiedName() {
-    return superState != null ? superState.getFullyQualifiedName() + '/' + name
-      : name;
+    return superState != null ? superState.getFullyQualifiedName() + '/' + name : name;
   }
 
   /** indicates wether this node is a superstate. */

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -63,8 +63,8 @@
   protected Map definitions;
 
   // event types //////////////////////////////////////////////////////////////
-
-  public static final String[] supportedEventTypes = {
+  
+  private static final String[] EVENT_TYPES = {
     Event.EVENTTYPE_PROCESS_START, Event.EVENTTYPE_PROCESS_END, Event.EVENTTYPE_NODE_ENTER,
     Event.EVENTTYPE_NODE_LEAVE, Event.EVENTTYPE_TASK_CREATE, Event.EVENTTYPE_TASK_ASSIGN,
     Event.EVENTTYPE_TASK_START, Event.EVENTTYPE_TASK_END, Event.EVENTTYPE_TRANSITION,
@@ -73,8 +73,14 @@
     Event.EVENTTYPE_SUBPROCESS_CREATED, Event.EVENTTYPE_SUBPROCESS_END, Event.EVENTTYPE_TIMER
   };
 
+  /**
+   * @deprecated arrays are mutable and thus vulnerable to external manipulation.
+   * use {@link #getSupportedEventTypes()} instead
+   */
+  public static final String[] supportedEventTypes = (String[]) EVENT_TYPES.clone();
+
   public String[] getSupportedEventTypes() {
-    return supportedEventTypes;
+    return (String[]) EVENT_TYPES.clone();
   }
 
   // constructors /////////////////////////////////////////////////////////////

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Transition.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Transition.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/def/Transition.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -44,11 +44,18 @@
 
   // event types //////////////////////////////////////////////////////////////
 
-  public static final String[] supportedEventTypes =
-      { Event.EVENTTYPE_TRANSITION };
+  private static final String[] EVENT_TYPES = {
+    Event.EVENTTYPE_TRANSITION
+  };
 
+  /**
+   * @deprecated arrays are mutable and thus vulnerable to external
+   * manipulation. use {@link #getSupportedEventTypes()} instead
+   */
+  public static final String[] supportedEventTypes = (String[]) EVENT_TYPES.clone();
+
   public String[] getSupportedEventTypes() {
-    return supportedEventTypes;
+    return (String[]) EVENT_TYPES.clone();
   }
 
   // constructors /////////////////////////////////////////////////////////////
@@ -117,25 +124,21 @@
     Token token = executionContext.getToken();
 
     if (condition != null && isConditionEnforced) {
-      Object result =
-          JbpmExpressionEvaluator.evaluate(condition, executionContext);
+      Object result = JbpmExpressionEvaluator.evaluate(condition, executionContext);
       if (result == null) {
-        throw new JbpmException("transition condition " + condition
-          + " evaluated to null");
+        throw new JbpmException("condition evaluated to null: " + condition);
       }
       else if (!(result instanceof Boolean)) {
-        throw new JbpmException("transition condition " + condition
-          + " evaluated to non-boolean: " + result.getClass().getName());
+        throw new JbpmException("condition result is not boolean: " + condition);
       }
       else if (((Boolean) result).booleanValue() == false) {
-        throw new JbpmException("transition condition " + condition
-          + " evaluated to 'false'");
+        throw new JbpmException("condition is false: " + condition);
       }
     }
 
     // start the transition log
-    TransitionLog transitionLog =
-        new TransitionLog(this, executionContext.getTransitionSource());
+    TransitionLog transitionLog = new TransitionLog(this, executionContext
+      .getTransitionSource());
     token.startCompositeLog(transitionLog);
     try {
       // fire leave events for superstates (if any)
@@ -162,15 +165,12 @@
     Node destination = to;
     while (destination != null && destination.isSuperStateNode()) {
       List nodes = destination.getNodes();
-      destination =
-          nodes != null && !nodes.isEmpty() ? (Node) nodes.get(0) : null;
+      destination = nodes != null && !nodes.isEmpty() ? (Node) nodes.get(0) : null;
     }
 
     if (destination == null) {
-      String transitionName =
-          name != null ? '\'' + name + '\'' : "in node '" + from + '\'';
-      throw new JbpmException("transition " + transitionName
-        + " has no destination");
+      String transitionName = name != null ? '\'' + name + '\'' : "in node '" + from + '\'';
+      throw new JbpmException("transition " + transitionName + " has no destination");
     }
 
     // optimisation: check if there is a candidate superstate to be entered
@@ -180,9 +180,8 @@
       // reverse order so that events fire from outer to inner superstates
       Collections.reverse(leavingSuperStates);
       // fire a superstate-enter event for all superstates being left
-      fireSuperStateEvents(leavingSuperStates,
-          Event.EVENTTYPE_SUPERSTATE_ENTER,
-          executionContext);
+      fireSuperStateEvents(leavingSuperStates, Event.EVENTTYPE_SUPERSTATE_ENTER,
+        executionContext);
     }
 
     return destination;
@@ -192,12 +191,11 @@
     // optimisation: check if there is a candidate superstate to be left
     if (executionContext.getTransitionSource().getSuperState() != null) {
       // collect all the superstates being left
-      List leavingSuperStates =
-          collectAllSuperStates(executionContext.getTransitionSource(), to);
+      List leavingSuperStates = collectAllSuperStates(executionContext.getTransitionSource(),
+        to);
       // fire a node-leave event for all superstates being left
-      fireSuperStateEvents(leavingSuperStates,
-          Event.EVENTTYPE_SUPERSTATE_LEAVE,
-          executionContext);
+      fireSuperStateEvents(leavingSuperStates, Event.EVENTTYPE_SUPERSTATE_LEAVE,
+        executionContext);
     }
   }
 
@@ -223,7 +221,7 @@
    * fires the give event on all the superstates in the list.
    */
   void fireSuperStateEvents(List superStates, String eventType,
-      ExecutionContext executionContext) {
+    ExecutionContext executionContext) {
     for (Iterator iter = superStates.iterator(); iter.hasNext();) {
       SuperState leavingSuperState = (SuperState) iter.next();
       leavingSuperState.fireEvent(eventType, executionContext);
@@ -239,8 +237,7 @@
     Transition other = (Transition) o;
     if (id != 0 && id == other.getId()) return true;
 
-    return (name != null ? name.equals(other.getName())
-        : other.getName() == null)
+    return (name != null ? name.equals(other.getName()) : other.getName() == null)
       && from != null && from.equals(other.getFrom());
   }
 
@@ -258,12 +255,8 @@
   public void setName(String name) {
     if (from != null) {
       if (from.hasLeavingTransition(name)) {
-        throw new IllegalArgumentException(
-            "couldn't set name '"
-              + name
-              + "' on transition '"
-              + this
-              + "'cause the from-node of this transition has already another leaving transition with the same name");
+        throw new IllegalArgumentException("cannot rename " + this
+          + " because " + from + " already has a transition named " + name);
       }
       Map fromLeavingTransitions = from.getLeavingTransitionsMap();
       fromLeavingTransitions.put(name, this);
@@ -276,9 +269,9 @@
       if (from.equals(to)) return from.getParent();
 
       for (GraphElement fromParent = from; fromParent != null; fromParent =
-          fromParent.getParent()) {
+        fromParent.getParent()) {
         for (GraphElement toParent = to; toParent != null; toParent =
-            toParent.getParent()) {
+          toParent.getParent()) {
           if (fromParent.equals(toParent)) return fromParent;
         }
       }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/graph/node/Decision.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -43,12 +43,11 @@
  */
 public class Decision extends Node implements Parsable {
 
-  static final String DECISION_CONDITION_RESULT = "decision_condition_result";
-  static final long serialVersionUID = 1L;
+  private List decisionConditions;
+  private Delegation decisionDelegation;
+  private String decisionExpression;
 
-  List decisionConditions = null;
-  Delegation decisionDelegation = null;
-  String decisionExpression = null;
+  private static final long serialVersionUID = 1L;
 
   public Decision() {
   }
@@ -75,107 +74,107 @@
   }
 
   public void execute(ExecutionContext executionContext) {
-    Transition transition = null;
-    ClassLoader surroundingClassLoader = Thread.currentThread().getContextClassLoader();
+    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
     try {
-      // set context class loader correctly for delegation class (https://jira.jboss.org/jira/browse/JBPM-1448)
-      Thread.currentThread().setContextClassLoader(
-          JbpmConfiguration.getProcessClassLoader(executionContext.getProcessDefinition()));
+      // set context class loader correctly for delegation class
+      // https://jira.jboss.org/jira/browse/JBPM-1448
+      ClassLoader processClassLoader = JbpmConfiguration.getProcessClassLoader(executionContext
+        .getProcessDefinition());
+      Thread.currentThread().setContextClassLoader(processClassLoader);
 
+      Transition transition = null;
       try {
         if (decisionDelegation != null) {
           DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation.getInstance();
-          if (decisionHandler == null)
-            decisionHandler = (DecisionHandler) decisionDelegation.instantiate();
-
           String transitionName = decisionHandler.decide(executionContext);
           transition = getLeavingTransition(transitionName);
           if (transition == null) {
-            throw new JbpmException("decision '"
-                + name
-                + "' selected non existing transition '"
-                + transitionName
-                + "'");
+            throw new JbpmException("no such transition: " + transitionName);
           }
         }
         else if (decisionExpression != null) {
-          Object result = JbpmExpressionEvaluator.evaluate(decisionExpression, executionContext);
+          Object result = JbpmExpressionEvaluator
+            .evaluate(decisionExpression, executionContext);
           if (result == null) {
-            throw new JbpmException("decision expression '"
-                + decisionExpression
-                + "' returned null");
+            throw new JbpmException("expression evaluated to null: " + decisionExpression);
           }
           String transitionName = result.toString();
           transition = getLeavingTransition(transitionName);
           if (transition == null) {
-            throw new JbpmException("decision '"
-                + name
-                + "' selected non existing transition '"
-                + transitionName
-                + "'");
+            throw new JbpmException("no such transition: " + transitionName);
           }
         }
         else if (decisionConditions != null && !decisionConditions.isEmpty()) {
-          // backwards compatible mode based on separate DecisionCondition's
-          Iterator iter = decisionConditions.iterator();
-          while (iter.hasNext() && (transition == null)) {
+          // backwards compatible mode based on separate DecisionConditions
+          for (Iterator iter = decisionConditions.iterator(); iter.hasNext();) {
             DecisionCondition decisionCondition = (DecisionCondition) iter.next();
-            Object result = JbpmExpressionEvaluator.evaluate(decisionCondition.getExpression(),
-                executionContext);
+            // evaluate condition
+            String expression = decisionCondition.getExpression();
+            Object result = JbpmExpressionEvaluator.evaluate(expression, executionContext);
+            // if condition was true
             if (Boolean.TRUE.equals(result)) {
+              // fetch name associated to condition
               String transitionName = decisionCondition.getTransitionName();
+              // select transition by name
               transition = getLeavingTransition(transitionName);
               if (transition != null) {
                 transition.removeConditionEnforcement();
+                break;
               }
             }
           }
         }
         else {
           // new mode based on conditions in the transition itself
-          Iterator iter = leavingTransitions.iterator();
-          while (iter.hasNext() && (transition == null)) {
+          for (Iterator iter = leavingTransitions.iterator(); iter.hasNext();) {
             Transition candidate = (Transition) iter.next();
-
-            String conditionExpression = candidate.getCondition();
-            if (conditionExpression != null) {
-              Object result = JbpmExpressionEvaluator.evaluate(conditionExpression,
-                  executionContext);
+            // evaluate condition if present
+            String condition = candidate.getCondition();
+            if (condition != null) {
+              Object result = JbpmExpressionEvaluator.evaluate(condition, executionContext);
+              // if condition was true
               if (Boolean.TRUE.equals(result)) {
+                // select transition associated to condition
                 transition = candidate;
+                break;
               }
             }
           }
         }
-
-        if (transition == null) transition = getDefaultLeavingTransition();
-
-        if (transition == null)
-          throw new IllegalStateException("decision cannot select transition: " + this);
-
-        log.debug("decision didn't select transition, taking default " + transition);
-
-        // since the decision node evaluates condition expressions,
-        // the condition of the taken transition will always be met.
-        // therefore we can safely turn off the standard condition enforcement
-        // in the transitions after a decision node.
-        transition.removeConditionEnforcement();
       }
       catch (Exception exception) {
         raiseException(exception, executionContext);
       }
+
+      // if no transition was selected, just take the default
+      if (transition == null) {
+        transition = getDefaultLeavingTransition();
+        // if there is no default transition, complain
+        if (transition == null) throw new JbpmException(this + " has no default transition");
+      }
+
+      // since the decision node evaluates transition conditions,
+      // the condition of the taken transition will always be met.
+      // therefore we can safely turn off the standard condition enforcement
+      // in the transitions after a decision node.
+      transition.removeConditionEnforcement();
+
+      log.debug(executionContext.getToken() + " leaves " + this + " over " + transition);
+      executionContext.leaveNode(transition);
     }
     finally {
-      Thread.currentThread().setContextClassLoader(surroundingClassLoader);
+      Thread.currentThread().setContextClassLoader(contextClassLoader);
     }
-    log.debug("decision " + name + " is taking '" + transition + "'");
-    executionContext.leaveNode(transition);
   }
 
   public List getDecisionConditions() {
     return decisionConditions;
   }
 
+  public Delegation getDecisionDelegation() {
+    return decisionDelegation;
+  }
+
   public void setDecisionDelegation(Delegation decisionDelegation) {
     this.decisionDelegation = decisionDelegation;
   }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/el/impl/JbpmExpressionEvaluator.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/el/impl/JbpmExpressionEvaluator.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/jpdl/el/impl/JbpmExpressionEvaluator.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -12,26 +12,35 @@
 
   private static ExpressionEvaluator expressionEvaluator;
 
-  static ExpressionEvaluator getExpressionEvaluator() {
+  private static ExpressionEvaluator getExpressionEvaluator() {
     return expressionEvaluator != null ? expressionEvaluator
-        : (ExpressionEvaluator) JbpmConfiguration.Configs.getObject("jbpm.expression.evaluator");
+      : (ExpressionEvaluator) JbpmConfiguration.Configs.getObject("jbpm.expression.evaluator");
   }
 
-  /** @deprecated Use the configuration entry <code>jbpm.expression.evaluator</code> instead */
+  /**
+   * @deprecated set configuration entry <code>jbpm.expression.evaluator</code>
+   * instead
+   */
   public static void setExpressionEvaluator(ExpressionEvaluator expressionEvaluator) {
     JbpmExpressionEvaluator.expressionEvaluator = expressionEvaluator;
   }
 
-  static VariableResolver variableResolver;
+  private static VariableResolver variableResolver;
 
-  /** @deprecated Use the configuration entry <code>jbpm.variable.resolver</code> instead */
+  /**
+   * @deprecated set configuration entry <code>jbpm.variable.resolver</code>
+   * instead
+   */
   public static void setVariableResolver(VariableResolver variableResolver) {
     JbpmExpressionEvaluator.variableResolver = variableResolver;
   }
 
-  static FunctionMapper functionMapper;
+  private static FunctionMapper functionMapper;
 
-  /** @deprecated Use the configuration entry <code>jbpm.function.mapper</code> instead */
+  /**
+   * @deprecated set configuration entry <code>jbpm.function.mapper</code>
+   * instead
+   */
   public static void setFunctionMapper(FunctionMapper functionMapper) {
     JbpmExpressionEvaluator.functionMapper = functionMapper;
   }
@@ -41,26 +50,26 @@
   }
 
   public static Object evaluate(String expression, ExecutionContext executionContext,
-      VariableResolver variableResolver, FunctionMapper functionMapper) {
+    VariableResolver variableResolver, FunctionMapper functionMapper) {
     ExecutionContext.pushCurrentContext(executionContext);
     try {
       String dollarExpression = translateExpressionToDollars(expression);
       return getExpressionEvaluator().evaluate(dollarExpression, Object.class,
-          variableResolver, functionMapper);
+        variableResolver, functionMapper);
     }
     catch (ELException e) {
-      throw new JbpmException("couldn't evaluate expression '" + expression + "'",
-          e.getRootCause() != null ? e.getRootCause() : e);
+      Throwable rootCause = e.getRootCause();
+      throw new JbpmException("failed to evaluate " + expression, rootCause != null ? rootCause : e);
     }
     finally {
       ExecutionContext.popCurrentContext(executionContext);
     }
   }
 
-  static String translateExpressionToDollars(String expression) {
+  private static String translateExpressionToDollars(String expression) {
     int hashIndex = expression.indexOf("#{");
     if (hashIndex == -1) return expression;
-    
+
     char[] expressionChars = expression.toCharArray();
     do {
       expressionChars[hashIndex] = '$';
@@ -76,7 +85,7 @@
 
   public static VariableResolver getVariableResolver() {
     return variableResolver != null ? variableResolver
-        : (VariableResolver) JbpmConfiguration.Configs.getObject("jbpm.variable.resolver");
+      : (VariableResolver) JbpmConfiguration.Configs.getObject("jbpm.variable.resolver");
   }
 
   /** @deprecated Use {@link #getFunctionMapper()} instead */
@@ -85,9 +94,8 @@
   }
 
   public static FunctionMapper getFunctionMapper() {
-    return functionMapper != null ? functionMapper
-        : JbpmConfiguration.Configs.hasObject("jbpm.function.mapper") ?
-            (FunctionMapper) JbpmConfiguration.Configs.getObject("jbpm.function.mapper")
-            : null;
+    return functionMapper != null ? functionMapper : JbpmConfiguration.Configs
+      .hasObject("jbpm.function.mapper") ? (FunctionMapper) JbpmConfiguration.Configs
+      .getObject("jbpm.function.mapper") : null;
   }
 }

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/def/Task.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/def/Task.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/java/org/jbpm/taskmgmt/def/Task.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -83,14 +83,15 @@
 
   // event types //////////////////////////////////////////////////////////////
 
-  static final String[] supportedEventTypes = {
+  private static final String[] EVENT_TYPES = {
     Event.EVENTTYPE_TASK_CREATE,
     Event.EVENTTYPE_TASK_ASSIGN,
     Event.EVENTTYPE_TASK_START,
     Event.EVENTTYPE_TASK_END
   };
+
   public String[] getSupportedEventTypes() {
-    return supportedEventTypes;
+    return (String[]) EVENT_TYPES.clone();
   }
 
   // task instance factory methods ////////////////////////////////////////////

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/jpdl/xml/jpdl-3.2.xsd
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/jpdl/xml/jpdl-3.2.xsd	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/main/resources/org/jbpm/jpdl/xml/jpdl-3.2.xsd	2010-03-04 13:17:09 UTC (rev 6209)
@@ -213,6 +213,7 @@
       </xs:choice>
       <xs:attribute name="to" type="xs:string" use="required" />
       <xs:attribute name="name" type="xs:string" />
+      <xs:attribute name="condition" type="xs:string" />
     </xs:complexType>
   </xs:element>
 

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/graph/node/JpdlDbTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/graph/node/JpdlDbTest.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/graph/node/JpdlDbTest.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -34,8 +34,8 @@
 import org.jbpm.taskmgmt.def.Task;
 
 public class JpdlDbTest extends AbstractDbTestCase {
-  
-  public void testDecision(){
+
+  public void testDecision() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
       "  <decision name='d'>" +
@@ -50,34 +50,29 @@
       "    </transition>" +
       "  </decision>" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Decision decision = (Decision) processDefinition.getNode("d");
       assertEquals("a == 1", decision.getLeavingTransition("one").getCondition());
       assertEquals("a == 2", decision.getLeavingTransition("two").getCondition());
       assertEquals("a == 3", decision.getLeavingTransition("three").getCondition());
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
-  public static class MyDecisionHandler implements DecisionHandler
-  {
+
+  public static class MyDecisionHandler implements DecisionHandler {
     private static final long serialVersionUID = 1L;
     String decisionHandlerConfigText = null;
 
-    public String decide(ExecutionContext executionContext) throws Exception
-    {
+    public String decide(ExecutionContext executionContext) throws Exception {
       return "two";
     }
   }
 
-  public void testDecisionDelegation(){
+  public void testDecisionDelegation() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
       "  <decision name='d' >" +
@@ -89,22 +84,20 @@
       "    <transition name='three' to='d'/>" +
       "  </decision>" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Decision decision = (Decision) processDefinition.getNode("d");
-      Delegation decisionDelegation = decision.decisionDelegation;
+      Delegation decisionDelegation = decision.getDecisionDelegation();
       assertNotNull(decisionDelegation);
-      assertEquals("org.jbpm.graph.node.JpdlDbTest$MyDecisionHandler", decisionDelegation.getClassName());
+      assertEquals("org.jbpm.graph.node.JpdlDbTest$MyDecisionHandler", decisionDelegation
+        .getClassName());
       MyDecisionHandler decisionHandler = (MyDecisionHandler) decisionDelegation.instantiate();
       assertEquals("testing... one, two... testing", decisionHandler.decisionHandlerConfigText);
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
 
   public void testFork() {
@@ -112,39 +105,33 @@
       "<process-definition>" +
       "  <fork name='f' />" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Fork fork = (Fork) processDefinition.getNode("f");
       assertNotNull(fork);
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
+
   public void testJoin() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
       "  <join name='j' />" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Join join = (Join) processDefinition.getNode("j");
       assertNotNull(join);
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
+
   public void testScript() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
@@ -156,41 +143,35 @@
       "    <expression>e = m * Math.pow(c,2);</expression>" +
       "  </script>" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Script script = (Script) processDefinition.getAction("s");
       assertNotNull(script);
-      assertEquals(4, script.getVariableAccesses().size() ); 
-      assertEquals("e = m * Math.pow(c,2);", script.getExpression() ); 
+      assertEquals(4, script.getVariableAccesses().size());
+      assertEquals("e = m * Math.pow(c,2);", script.getExpression());
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
+
   public void testState() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
       "  <state name='s' />" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       State state = (State) processDefinition.getNode("s");
       assertNotNull(state);
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
+
   public void testTaskNode() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
@@ -203,17 +184,16 @@
       "  </task-node>" +
       "</process-definition>"
     );
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       TaskNode taskNode = (TaskNode) processDefinition.getNode("t");
       assertNotNull(taskNode);
       assertEquals("t", taskNode.getName());
       assertEquals(TaskNode.SIGNAL_FIRST_WAIT, taskNode.getSignal());
       assertFalse(taskNode.getCreateTasks());
       assertEquals(3, taskNode.getTasks().size());
-      
+
       Map tasks = new HashMap();
       Iterator iter = taskNode.getTasks().iterator();
       while (iter.hasNext()) {
@@ -225,22 +205,20 @@
       assertSame(taskNode, task.getTaskNode());
       assertTrue(task.isBlocking());
       assertEquals("anyonebutme", task.getAssignmentDelegation().getClassName());
-      
+
       task = (Task) tasks.get("change the world twice");
       assertNotNull(task);
       assertSame(taskNode, task.getTaskNode());
       assertFalse(task.isBlocking());
 
-      assertTrue(tasks.containsKey("change the world three times") );
+      assertTrue(tasks.containsKey("change the world three times"));
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
   }
-  
-  public void testNoAccessToObsoleteDecisionConditionTable(){
+
+  public void testNoAccessToObsoleteDecisionConditionTable() {
     ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
       "<process-definition>" +
       " <start-state>" +
@@ -261,15 +239,14 @@
       " <state name='b' />" +
       " <state name='c' />" +
       "</process-definition>");
-    
+
     processDefinition = saveAndReload(processDefinition);
-    try
-    {
+    try {
       Decision decision = (Decision) processDefinition.getNode("d");
       assertEquals("#{a == 1}", decision.getLeavingTransition("one").getCondition());
       assertEquals("#{a == 2}", decision.getLeavingTransition("two").getCondition());
       assertEquals("#{a == 3}", decision.getLeavingTransition("three").getCondition());
-      
+
       // Assure org.jbpm.graph.node.Decision#execute gets the conditions from
       // table JBPM_TRANSITIONS rather than the obsolete JBPM_DECISIONCONDITION:
       ProcessInstance processInstance = new ProcessInstance(processDefinition);
@@ -277,10 +254,8 @@
       processInstance.signal();
       assertEquals(processDefinition.getNode("b"), processInstance.getRootToken().getNode());
     }
-    finally
-    {
+    finally {
       jbpmContext.getGraphSession().deleteProcessDefinition(processDefinition.getId());
     }
-    
-  } 
+  }
 }

Added: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/JBPM2784Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/JBPM2784Test.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/JBPM2784Test.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.jbpm2784;
+
+import java.util.Random;
+
+import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.context.exe.ContextInstance;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+
+/**
+ * JBPM-2784: XML schema does not accept condition attribute in transition.
+ * 
+ * @author Alejandro Guizar
+ * @see <a href="https://jira.jboss.org/jira/browse/JBPM-2784">JBPM-2784</a>
+ */
+public class JBPM2784Test extends AbstractJbpmTestCase {
+
+  public void testTransitionConditionAttribute() {
+    ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<?xml version='1.0'?>"
+      + "<process-definition name='jbpm2784' xmlns='urn:jbpm.org:jpdl-3.2'>"
+      + "  <start-state name='start'>"
+      + "    <transition to='blackjack'/>"
+      + "  </start-state>"
+      + "  <decision name='blackjack'>"
+      + "    <transition name='hit' to='hit' condition='${count &lt; 17}'/>"
+      + "    <transition name='stand' to='stand'/>"
+      + "  </decision>"
+      + "  <end-state name='hit'/>"
+      + "  <end-state name='stand'/>"
+      + "</process-definition>");
+
+    ProcessInstance processInstance = new ProcessInstance(processDefinition);
+
+    int count = new Random().nextInt(21) + 1;
+    ContextInstance contextInstance = processInstance.getContextInstance();
+    contextInstance.setVariable("count", new Integer(count));
+
+    processInstance.signal();
+    assertTrue("expected " + processInstance + " to have ended", processInstance.hasEnded());
+
+    assertEquals(count < 17 ? "hit" : "stand", processInstance.getRootToken()
+      .getNode()
+      .getName());
+  }
+}


Property changes on: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jbpm2784/JBPM2784Test.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Modified: jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/el/DecisionExpressionTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/el/DecisionExpressionTest.java	2010-03-04 07:33:35 UTC (rev 6208)
+++ jbpm3/branches/jbpm-3.2-soa/modules/core/src/test/java/org/jbpm/jpdl/el/DecisionExpressionTest.java	2010-03-04 13:17:09 UTC (rev 6209)
@@ -69,7 +69,7 @@
       fail("expected exception");
     }
     catch (JbpmException e) {
-      assertTrue(e.getMessage().indexOf("non existing transition") != -1);
+      assert e.getMessage().indexOf("UNDEFINED") != -1 : e;
     }
   }
 
@@ -82,7 +82,7 @@
       fail("expected exception");
     }
     catch (JbpmException e) {
-      // OK
+      assert e.getMessage().indexOf("null") != -1 : e;
     }
   }
 



More information about the jbpm-commits mailing list