Skip to content

Commit

Permalink
#3884 Expression language support for conditional sequence flow and c…
Browse files Browse the repository at this point in the history
…onditional events (#3889)

* #3884 Expression language support for conditional sequence flow and conditional events

* #3884: Use ScriptCondition instead of ScriptEngineExpression

* #3884: Move logic to ConditionUtil and leave ScriptCondition unchanged

* #3884: Rename sequenceFlowId to elementId. Revert whitespace-only changes.

* #3884: Pass the id of the event definition instead of the activity
  • Loading branch information
rasmusfaber authored Oct 3, 2024
1 parent 0069d6a commit d1a8c91
Show file tree
Hide file tree
Showing 26 changed files with 257 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,10 @@ protected void writeConditionalDefinition(Event parentEvent, ConditionalEventDef

if (StringUtils.isNotEmpty(conditionalDefinition.getConditionExpression())) {
xtw.writeStartElement(ELEMENT_CONDITION);
if (conditionalDefinition.getConditionLanguage() != null) {
xtw.writeAttribute(XSI_PREFIX, XSI_NAMESPACE, "type", "tFormalExpression");
BpmnXMLUtil.writeDefaultAttribute(BpmnXMLConstants.ATTRIBUTE_SCRIPT_LANGUAGE, conditionalDefinition.getConditionLanguage(), xtw);
}
xtw.writeCharacters(conditionalDefinition.getConditionExpression());
xtw.writeEndElement();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import javax.xml.stream.XMLStreamWriter;

import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.converter.util.BpmnXMLUtil;
import org.flowable.bpmn.model.BaseElement;
import org.flowable.bpmn.model.BpmnModel;
Expand Down Expand Up @@ -66,6 +67,9 @@ protected void writeAdditionalChildElements(BaseElement element, BpmnModel model
if (StringUtils.isNotEmpty(sequenceFlow.getConditionExpression())) {
xtw.writeStartElement(ELEMENT_FLOW_CONDITION);
xtw.writeAttribute(XSI_PREFIX, XSI_NAMESPACE, "type", "tFormalExpression");
if (sequenceFlow.getConditionLanguage() != null) {
BpmnXMLUtil.writeDefaultAttribute(BpmnXMLConstants.ATTRIBUTE_SCRIPT_LANGUAGE, sequenceFlow.getConditionLanguage(), xtw);
}
xtw.writeCData(sequenceFlow.getConditionExpression());
xtw.writeEndElement();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ public String getElementName() {

@Override
public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception {
if (!(parentElement instanceof SequenceFlow)) {
if (!(parentElement instanceof SequenceFlow sequenceFlow)) {
return;
}

((SequenceFlow) parentElement).setConditionExpression(xtr.getElementText().trim());
sequenceFlow.setConditionLanguage(xtr.getAttributeValue(null, ATTRIBUTE_SCRIPT_LANGUAGE));
sequenceFlow.setConditionExpression(xtr.getElementText().trim());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ public String getElementName() {

@Override
public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception {
if (!(parentElement instanceof ConditionalEventDefinition)) {
if (!(parentElement instanceof ConditionalEventDefinition conditionalEventDefinition)) {
return;
}

((ConditionalEventDefinition) parentElement).setConditionExpression(xtr.getElementText().trim());
conditionalEventDefinition.setConditionLanguage(xtr.getAttributeValue(null, ATTRIBUTE_SCRIPT_LANGUAGE));
conditionalEventDefinition.setConditionExpression(xtr.getElementText().trim());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
public class ConditionalEventDefinition extends EventDefinition {

protected String conditionExpression;
protected String conditionLanguage;

public String getConditionExpression() {
return conditionExpression;
Expand All @@ -27,6 +28,14 @@ public void setConditionExpression(String conditionExpression) {
this.conditionExpression = conditionExpression;
}

public String getConditionLanguage() {
return conditionLanguage;
}

public void setConditionLanguage(String conditionLanguage) {
this.conditionLanguage = conditionLanguage;
}

@Override
public ConditionalEventDefinition clone() {
ConditionalEventDefinition clone = new ConditionalEventDefinition();
Expand All @@ -37,5 +46,6 @@ public ConditionalEventDefinition clone() {
public void setValues(ConditionalEventDefinition otherDefinition) {
super.setValues(otherDefinition);
setConditionExpression(otherDefinition.getConditionExpression());
setConditionLanguage(otherDefinition.getConditionLanguage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class SequenceFlow extends FlowElement {

protected String conditionExpression;
protected String conditionLanguage;
protected String sourceRef;
protected String targetRef;
protected String skipExpression;
Expand Down Expand Up @@ -60,6 +61,14 @@ public void setConditionExpression(String conditionExpression) {
this.conditionExpression = conditionExpression;
}

public String getConditionLanguage() {
return conditionLanguage;
}

public void setConditionLanguage(String conditionLanguage) {
this.conditionLanguage = conditionLanguage;
}

public String getSourceRef() {
return sourceRef;
}
Expand Down Expand Up @@ -123,6 +132,7 @@ public SequenceFlow clone() {
public void setValues(SequenceFlow otherFlow) {
super.setValues(otherFlow);
setConditionExpression(otherFlow.getConditionExpression());
setConditionLanguage(otherFlow.getConditionLanguage());
setSourceRef(otherFlow.getSourceRef());
setTargetRef(otherFlow.getTargetRef());
setSkipExpression(otherFlow.getSkipExpression());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ public interface FlowableConditionalEvent extends FlowableActivityEvent {
*/
String getConditionExpression();

/**
* @return the scripting language of the condition expression.
*/
String getConditionLanguage();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
public class FlowableConditionalEventImpl extends FlowableActivityEventImpl implements FlowableConditionalEvent {

protected String conditionExpression;
protected String conditionLanguage;

public FlowableConditionalEventImpl(FlowableEngineEventType type) {
super(type);
Expand All @@ -34,4 +35,12 @@ public String getConditionExpression() {
public void setConditionExpression(String conditionExpression) {
this.conditionExpression = conditionExpression;
}

public String getConditionLanguage() {
return conditionLanguage;
}

public void setConditionLanguage(String conditionLanguage) {
this.conditionLanguage = conditionLanguage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ public static FlowableMessageEvent createMessageEvent(FlowableEngineEventType ty
return newEvent;
}

public static FlowableConditionalEvent createConditionalEvent(FlowableEngineEventType type, String activityId, String conditionExpression,
public static FlowableConditionalEvent createConditionalEvent(FlowableEngineEventType type, String activityId, String conditionExpression, String conditionLanguage,
String executionId, String processInstanceId, String processDefinitionId) {

FlowableConditionalEventImpl newEvent = new FlowableConditionalEventImpl(type);
Expand All @@ -377,6 +377,7 @@ public static FlowableConditionalEvent createConditionalEvent(FlowableEngineEven
newEvent.setProcessDefinitionId(processDefinitionId);
newEvent.setProcessInstanceId(processInstanceId);
newEvent.setConditionExpression(conditionExpression);
newEvent.setConditionLanguage(conditionLanguage);
return newEvent;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
*/
public interface Condition extends Serializable {

boolean evaluate(String sequenceFlowId, DelegateExecution execution);
boolean evaluate(String elementId, DelegateExecution execution);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.debug.ExecutionTreeUtil;
import org.flowable.engine.impl.Condition;
import org.flowable.engine.impl.delegate.ActivityBehavior;
import org.flowable.engine.impl.delegate.TriggerableActivityBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.scripting.ScriptCondition;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.impl.util.condition.ConditionUtil;

/**
* Operation that triggers conditional events for which the condition evaluate to true and continues the process, leaving that activity.
Expand Down Expand Up @@ -92,11 +95,8 @@ protected void evaluateEventSubProcesses(List<EventSubProcess> eventSubProcesses
boolean conditionIsTrue = false;
String conditionExpression = conditionalEventDefinition.getConditionExpression();
if (StringUtils.isNotEmpty(conditionExpression)) {
Expression expression = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager().createExpression(conditionExpression);
Object result = expression.getValue(parentExecution);
if (result instanceof Boolean && (Boolean) result) {
conditionIsTrue = true;
}
String conditionLanguage = conditionalEventDefinition.getConditionLanguage();
conditionIsTrue = ConditionUtil.hasTrueCondition(startEvent.getId(), conditionExpression, conditionLanguage, parentExecution);

} else {
conditionIsTrue = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.event.impl.FlowableEventBuilder;
import org.flowable.engine.impl.Condition;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.scripting.ScriptCondition;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.condition.ConditionUtil;

/**
* @author Tijs Rademakers
Expand All @@ -33,11 +36,13 @@ public class BoundaryConditionalEventActivityBehavior extends BoundaryEventActiv

protected ConditionalEventDefinition conditionalEventDefinition;
protected String conditionExpression;
protected String conditionLanguage;

public BoundaryConditionalEventActivityBehavior(ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, boolean interrupting) {
public BoundaryConditionalEventActivityBehavior(ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, String conditionLanguage, boolean interrupting) {
super(interrupting);
this.conditionalEventDefinition = conditionalEventDefinition;
this.conditionExpression = conditionExpression;
this.conditionLanguage = conditionLanguage;
}

@Override
Expand All @@ -48,7 +53,7 @@ public void execute(DelegateExecution execution) {
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(FlowableEventBuilder.createConditionalEvent(FlowableEngineEventType.ACTIVITY_CONDITIONAL_WAITING, executionEntity.getActivityId(),
conditionExpression, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
conditionExpression, conditionLanguage, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
processEngineConfiguration.getEngineCfgKey());
}
}
Expand All @@ -59,15 +64,14 @@ public void trigger(DelegateExecution execution, String triggerName, Object trig
ExecutionEntity executionEntity = (ExecutionEntity) execution;

ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
Expression expression = processEngineConfiguration.getExpressionManager().createExpression(conditionExpression);
Object result = expression.getValue(execution);
if (result instanceof Boolean && (Boolean) result) {
boolean result = ConditionUtil.hasTrueCondition(conditionalEventDefinition.getId(), conditionExpression, conditionLanguage, executionEntity);
if (result) {
processEngineConfiguration.getActivityInstanceEntityManager().recordActivityStart(executionEntity);

FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(FlowableEventBuilder.createConditionalEvent(FlowableEngineEventType.ACTIVITY_CONDITIONAL_RECEIVED, executionEntity.getActivityId(),
conditionExpression, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
conditionExpression, conditionLanguage, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
processEngineConfiguration.getEngineCfgKey());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ public class IntermediateCatchConditionalEventActivityBehavior extends Intermedi

protected ConditionalEventDefinition conditionalEventDefinition;
protected String conditionExpression;
protected String conditionLanguage;

public IntermediateCatchConditionalEventActivityBehavior(ConditionalEventDefinition conditionalEventDefinition, String conditionExpression) {
public IntermediateCatchConditionalEventActivityBehavior(ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, String conditionLanguage) {
this.conditionalEventDefinition = conditionalEventDefinition;
this.conditionExpression = conditionExpression;
this.conditionLanguage = conditionLanguage;
}

@Override
Expand All @@ -42,7 +44,7 @@ public void execute(DelegateExecution execution) {
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(FlowableEventBuilder.createConditionalEvent(FlowableEngineEventType.ACTIVITY_CONDITIONAL_WAITING,
executionEntity.getActivityId(), conditionExpression, executionEntity.getId(),
executionEntity.getActivityId(), conditionExpression, conditionLanguage, executionEntity.getId(),
executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
processEngineConfiguration.getEngineCfgKey());
}
Expand All @@ -59,7 +61,7 @@ public void trigger(DelegateExecution execution, String triggerName, Object trig
FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(FlowableEventBuilder.createConditionalEvent(FlowableEngineEventType.ACTIVITY_CONDITIONAL_RECEIVED, executionEntity.getActivityId(),
conditionExpression, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
conditionExpression, conditionLanguage, executionEntity.getId(), executionEntity.getProcessInstanceId(), executionEntity.getProcessDefinitionId()),
processEngineConfiguration.getEngineCfgKey());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ IntermediateCatchMessageEventActivityBehavior createIntermediateCatchMessageEven
MessageEventDefinition messageEventDefinition);

IntermediateCatchConditionalEventActivityBehavior createIntermediateCatchConditionalEventActivityBehavior(IntermediateCatchEvent intermediateCatchEvent,
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression);
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, String conditionLanguage);

IntermediateCatchTimerEventActivityBehavior createIntermediateCatchTimerEventActivityBehavior(IntermediateCatchEvent intermediateCatchEvent, TimerEventDefinition timerEventDefinition);

Expand Down Expand Up @@ -268,7 +268,7 @@ IntermediateCatchVariableListenerEventActivityBehavior createIntermediateCatchVa
BoundaryMessageEventActivityBehavior createBoundaryMessageEventActivityBehavior(BoundaryEvent boundaryEvent, MessageEventDefinition messageEventDefinition, boolean interrupting);

BoundaryConditionalEventActivityBehavior createBoundaryConditionalEventActivityBehavior(BoundaryEvent boundaryEvent, ConditionalEventDefinition conditionalEventDefinition,
String conditionExpression, boolean interrupting);
String conditionExpression, String conditionLanguage, boolean interrupting);

BoundaryEscalationEventActivityBehavior createBoundaryEscalationEventActivityBehavior(BoundaryEvent boundaryEvent, EscalationEventDefinition escalationEventDefinition, Escalation escalation, boolean interrupting);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,9 @@ public IntermediateCatchEventActivityBehavior createIntermediateCatchEventActivi

@Override
public IntermediateCatchConditionalEventActivityBehavior createIntermediateCatchConditionalEventActivityBehavior(IntermediateCatchEvent intermediateCatchEvent,
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression) {
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, String conditionLanguage) {

return new IntermediateCatchConditionalEventActivityBehavior(conditionalEventDefinition, conditionExpression);
return new IntermediateCatchConditionalEventActivityBehavior(conditionalEventDefinition, conditionExpression, conditionLanguage);
}

@Override
Expand Down Expand Up @@ -654,9 +654,9 @@ public BoundaryCompensateEventActivityBehavior createBoundaryCompensateEventActi

@Override
public BoundaryConditionalEventActivityBehavior createBoundaryConditionalEventActivityBehavior(BoundaryEvent boundaryEvent,
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, boolean interrupting) {
ConditionalEventDefinition conditionalEventDefinition, String conditionExpression, String conditionLanguage, boolean interrupting) {

return new BoundaryConditionalEventActivityBehavior(conditionalEventDefinition, conditionExpression, interrupting);
return new BoundaryConditionalEventActivityBehavior(conditionalEventDefinition, conditionExpression, conditionLanguage, interrupting);
}

@Override
Expand Down
Loading

0 comments on commit d1a8c91

Please sign in to comment.