001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.graph.node;
023:
024: import java.util.Iterator;
025: import java.util.List;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.dom4j.Element;
030: import org.jbpm.JbpmException;
031: import org.jbpm.graph.def.Node;
032: import org.jbpm.graph.def.Transition;
033: import org.jbpm.graph.exe.ExecutionContext;
034: import org.jbpm.instantiation.Delegation;
035: import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
036: import org.jbpm.jpdl.xml.JpdlXmlReader;
037: import org.jbpm.jpdl.xml.Parsable;
038:
039: /**
040: * decision node.
041: */
042: public class Decision extends Node implements Parsable {
043:
044: static final String NEWLINE = System.getProperty("line.separator");
045: static final String DECISION_CONDITION_RESULT = "decision_condition_result";
046: static final long serialVersionUID = 1L;
047:
048: List decisionConditions = null;
049: Delegation decisionDelegation = null;
050: String decisionExpression = null;
051:
052: public Decision() {
053: }
054:
055: public Decision(String name) {
056: super (name);
057: }
058:
059: public void read(Element decisionElement, JpdlXmlReader jpdlReader) {
060:
061: String expression = decisionElement
062: .attributeValue("expression");
063: Element decisionHandlerElement = decisionElement
064: .element("handler");
065:
066: if (expression != null) {
067: decisionExpression = expression;
068:
069: } else if (decisionHandlerElement != null) {
070: decisionDelegation = new Delegation();
071: decisionDelegation.read(decisionHandlerElement, jpdlReader);
072: }
073: }
074:
075: String getConditionExpression(Element conditionElement) {
076: String expression = conditionElement
077: .attributeValue("expression");
078: if (expression != null) {
079: return expression;
080: } else {
081: return conditionElement.getText();
082: }
083: }
084:
085: public void execute(ExecutionContext executionContext) {
086: Transition transition = null;
087:
088: try {
089: if (decisionDelegation != null) {
090: DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation
091: .instantiate();
092: String transitionName = decisionHandler
093: .decide(executionContext);
094: transition = getLeavingTransition(transitionName);
095: if (transition == null) {
096: throw new JbpmException("decision '" + name
097: + "' selected non existing transition '"
098: + transitionName + "'");
099: }
100:
101: } else if (decisionExpression != null) {
102: Object result = JbpmExpressionEvaluator.evaluate(
103: decisionExpression, executionContext);
104: if (result == null) {
105: throw new JbpmException("decision expression '"
106: + decisionExpression + "' returned null");
107: }
108: String transitionName = result.toString();
109: transition = getLeavingTransition(transitionName);
110: if (transition == null) {
111: throw new JbpmException("decision '" + name
112: + "' selected non existing transition '"
113: + transitionName + "'");
114: }
115:
116: } else if (decisionConditions != null
117: && !decisionConditions.isEmpty()) {
118: // backwards compatible mode based on separate DecisionCondition's
119: Iterator iter = decisionConditions.iterator();
120: while (iter.hasNext() && (transition == null)) {
121: DecisionCondition decisionCondition = (DecisionCondition) iter
122: .next();
123: Object result = JbpmExpressionEvaluator.evaluate(
124: decisionCondition.getExpression(),
125: executionContext);
126: if (Boolean.TRUE.equals(result)) {
127: if (transition != null) {
128: transition.removeConditionEnforcement();
129: }
130: String transitionName = decisionCondition
131: .getTransitionName();
132: transition = getLeavingTransition(transitionName);
133: }
134: }
135:
136: } else {
137: // new mode based on conditions in the transition itself
138: Iterator iter = leavingTransitions.iterator();
139: while (iter.hasNext() && (transition == null)) {
140: Transition candidate = (Transition) iter.next();
141:
142: String conditionExpression = candidate
143: .getCondition();
144: if (conditionExpression != null) {
145: Object result = JbpmExpressionEvaluator
146: .evaluate(conditionExpression,
147: executionContext);
148: if (Boolean.TRUE.equals(result)) {
149: transition = candidate;
150: }
151: }
152: }
153:
154: }
155:
156: if (transition == null) {
157: transition = getDefaultLeavingTransition();
158: log
159: .debug("decision didn't select transition, taking default "
160: + transition);
161: }
162:
163: // since the decision node evaluates condition expressions, the condition of the
164: // taken transition will always be met. therefor we can safely turn off the
165: // standard condition enforcement in the transitions after a decision node.
166: transition.removeConditionEnforcement();
167:
168: } catch (Exception exception) {
169: raiseException(exception, executionContext);
170: }
171:
172: log.debug("decision " + name + " is taking '" + transition
173: + "'");
174: executionContext.leaveNode(transition);
175: }
176:
177: public List getDecisionConditions() {
178: return decisionConditions;
179: }
180:
181: public void setDecisionDelegation(Delegation decisionDelegation) {
182: this .decisionDelegation = decisionDelegation;
183: }
184:
185: private static Log log = LogFactory.getLog(Decision.class);
186: }
|