de.viadee.bpm.vPAV.processing.ProcessVariableReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of viadeeProcessApplicationValidator Show documentation
Show all versions of viadeeProcessApplicationValidator Show documentation
The tool checks Camunda projects for consistency and discovers errors in process-driven applications.
Called as a JUnit test, it discovers esp. inconsistencies of a given BPMN model in the classpath and the
sourcecode of an underlying java project, such as a delegate reference to a non-existing java class or a
non-existing Spring bean.
/**
* BSD 3-Clause License
*
* Copyright © 2018, viadee Unternehmensberatung AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.viadee.bpm.vPAV.processing;
import de.viadee.bpm.vPAV.BpmnScanner;
import de.viadee.bpm.vPAV.FileScanner;
import de.viadee.bpm.vPAV.RuntimeConfig;
import de.viadee.bpm.vPAV.constants.BpmnConstants;
import de.viadee.bpm.vPAV.constants.ConfigConstants;
import de.viadee.bpm.vPAV.processing.model.data.*;
import org.camunda.bpm.engine.impl.juel.Builder;
import org.camunda.bpm.engine.impl.juel.IdentifierNode;
import org.camunda.bpm.engine.impl.juel.Tree;
import org.camunda.bpm.engine.impl.juel.TreeBuilder;
import org.camunda.bpm.model.bpmn.Query;
import org.camunda.bpm.model.bpmn.impl.BpmnModelConstants;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.camunda.*;
import org.camunda.bpm.model.dmn.Dmn;
import org.camunda.bpm.model.dmn.DmnModelInstance;
import org.camunda.bpm.model.dmn.instance.Decision;
import org.camunda.bpm.model.dmn.instance.InputExpression;
import org.camunda.bpm.model.dmn.instance.Output;
import org.camunda.bpm.model.dmn.instance.Text;
import org.camunda.bpm.model.xml.instance.ModelElementInstance;
import javax.el.ELException;
import java.io.InputStream;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* search process variables for an bpmn element
*
*/
public final class ProcessVariableReader {
private final Map decisionRefToPathMap;
private final BpmnScanner bpmnScanner;
public static final Logger LOGGER = Logger.getLogger(ProcessVariableReader.class.getName());
public ProcessVariableReader(final Map decisionRefToPathMap, BpmnScanner scanner) {
this.decisionRefToPathMap = decisionRefToPathMap;
this.bpmnScanner = scanner;
}
/**
* Examining an bpmn element for variables
*
* @param context
* JavaReaderContext (static vs regex)
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @param processVariables
* process variable operation
* @return returns processVariables
*/
public LinkedHashMap getVariablesFromElement(final JavaReaderContext context,
final FileScanner fileScanner, final BpmnElement element,
final LinkedHashMap processVariables) {
// 1) Search variables in task
processVariables.putAll(getVariablesFromTask(context, fileScanner, element));
// 2) Search variables in sequence flow
processVariables.putAll(searchVariablesFromSequenceFlow(context, fileScanner, element));
// 3) Search variables in ExtensionElements
processVariables.putAll(searchExtensionsElements(context, fileScanner, element));
// 4) Search variables in In/Output Parameters
processVariables.putAll(getVariablesFromParameters(element));
// 5) Search variables in Signal and Messagenames
processVariables.putAll(getVariablesFromNames(element));
return processVariables;
}
/**
*
* Retrieve process variables from names
*
* @param element
* BpmnElement
* @return processVariables returns processVariables
*/
private LinkedHashMap getVariablesFromNames(final BpmnElement element) {
final LinkedHashMap processVariables = new LinkedHashMap();
final BaseElement baseElement = element.getBaseElement();
final BpmnModelElementInstance scopeElement = baseElement.getScope();
String scopeElementId = null;
if (scopeElement != null) {
scopeElementId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
ArrayList signalRefs = bpmnScanner.getSignalRefs(element.getBaseElement().getId());
ArrayList messagesRefs = bpmnScanner.getMessageRefs(element.getBaseElement().getId());
ArrayList signalVariables = getSignalVariables(signalRefs, element);
ArrayList messageVariables = getMessageVariables(messagesRefs, element);
for (String variable : messageVariables) {
processVariables.put(variable,
new ProcessVariableOperation(variable, element, ElementChapter.General,
KnownElementFieldType.Message, element.getProcessdefinition(), VariableOperation.READ,
scopeElementId));
}
for (String variable : signalVariables) {
processVariables.put(variable,
new ProcessVariableOperation(variable, element, ElementChapter.General,
KnownElementFieldType.Signal, element.getProcessdefinition(), VariableOperation.READ,
scopeElementId));
}
return processVariables;
}
/**
*
* Retrieves variables from signal
*
* @param signalRefs
* List of signal references
* @param element
* BpmnElement
* @return variables
*/
private ArrayList getSignalVariables(ArrayList signalRefs, BpmnElement element) {
ArrayList names = new ArrayList();
for (String signalID : signalRefs) {
names.add(bpmnScanner.getSignalName(signalID));
}
ArrayList variables = new ArrayList();
for (String signalName : names) {
variables.addAll(checkExpressionForReadVariable(signalName, element));
}
return variables;
}
/**
*
* Retrieves variables from message
*
* @param messageRefs
* List of message references
* @param element
* BpmnElement
* @return variables
*/
private ArrayList getMessageVariables(ArrayList messageRefs, BpmnElement element) {
ArrayList names = new ArrayList();
for (String messageID : messageRefs) {
names.add(bpmnScanner.getMessageName(messageID));
}
ArrayList variables = new ArrayList();
for (String messageName : names) {
variables.addAll(checkExpressionForReadVariable(messageName, element));
}
return variables;
}
/**
* Analyze Output Parameters for variables
*
* @param element
* BpmnElement
* @return Map of ProcessVariable
*
*/
private LinkedHashMap getVariablesFromParameters(final BpmnElement element) {
final LinkedHashMap processVariables = new LinkedHashMap();
final BaseElement baseElement = element.getBaseElement();
final BpmnModelElementInstance scopeElement = baseElement.getScope();
String scopeElementId = null;
if (scopeElement != null) {
scopeElementId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
ArrayList outVar = bpmnScanner.getOutputVariables(element.getBaseElement().getId());
ArrayList inVar = bpmnScanner.getInputVariables(element.getBaseElement().getId());
ArrayList varValues = bpmnScanner.getInOutputVariablesValue(element.getBaseElement().getId());
// save output variables
for (String name : outVar) {
processVariables.put(name,
new ProcessVariableOperation(name, element, ElementChapter.InputOutput,
KnownElementFieldType.OutputParameter, element.getProcessdefinition(),
VariableOperation.WRITE, scopeElementId));
}
ArrayList varValueClean = new ArrayList();
for (String expression : varValues) {
varValueClean.addAll(checkExpressionForReadVariable(expression, element));
}
varValueClean.removeAll(inVar);
// add all processVariables to List
for (String var : varValueClean) {
processVariables.put(var,
new ProcessVariableOperation(var, element, ElementChapter.InputOutput,
KnownElementFieldType.OutputParameter, element.getProcessdefinition(),
VariableOperation.READ, scopeElementId));
}
for (String name : outVar)
processVariables.put(name,
new ProcessVariableOperation(name, element, ElementChapter.InputOutput,
KnownElementFieldType.OutputParameter, element.getProcessdefinition(),
VariableOperation.WRITE, scopeElementId));
return processVariables;
}
/**
* Analyze bpmn extension elements for variables
*
* @param context
* JavaReaderContext
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @return variables
*/
private LinkedHashMap searchExtensionsElements(final JavaReaderContext context,
final FileScanner fileScanner, final BpmnElement element) {
final LinkedHashMap processVariables = new LinkedHashMap();
final BaseElement baseElement = element.getBaseElement();
final BpmnModelElementInstance scopeElement = baseElement.getScope();
String scopeElementId = null;
if (scopeElement != null) {
scopeElementId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
final ExtensionElements extensionElements = baseElement.getExtensionElements();
if (extensionElements != null) {
// 1) Search in Execution Listeners
processVariables.putAll(getVariablesFromExecutionListener(context, fileScanner, element, extensionElements,
scopeElementId));
// 2) Search in Task Listeners
processVariables.putAll(
getVariablesFromTaskListener(context, fileScanner, element, extensionElements, scopeElementId));
// 3) Search in Form Data
processVariables.putAll(getVariablesFromFormData(element, extensionElements, scopeElementId));
// 4) Search in Input/Output-Associations (Call Activities)
processVariables.putAll(searchVariablesInInputOutputExtensions(element, extensionElements, scopeElementId));
}
return processVariables;
}
/**
* Get process variables from execution listeners
*
* @param context
* JavaReaderContext
* @param fileScanner
* FileScanner
* @param element
* Current BPMN Element
* @param extensionElements
* Extension elements (e.g. Listeners)
* @param scopeId
* Scope ID
* @return variables
*/
private LinkedHashMap getVariablesFromExecutionListener(
final JavaReaderContext context, final FileScanner fileScanner, final BpmnElement element,
final ExtensionElements extensionElements, final String scopeId) {
final LinkedHashMap processVariables = new LinkedHashMap();
List listenerList = extensionElements.getElementsQuery()
.filterByType(CamundaExecutionListener.class).list();
for (final CamundaExecutionListener listener : listenerList) {
final String l_expression = listener.getCamundaExpression();
if (l_expression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, l_expression, element,
ElementChapter.ExecutionListener, KnownElementFieldType.Expression, scopeId));
}
final String l_delegateExpression = listener.getCamundaDelegateExpression();
if (l_delegateExpression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, l_delegateExpression, element,
ElementChapter.ExecutionListener, KnownElementFieldType.DelegateExpression, scopeId));
}
final String l_class = listener.getCamundaClass();
if (l_class != null) {
LOGGER.warning("Entered getVariablesFromJavaDelegate from getVariablesFromExecutionListener for "
+ element.getBaseElement().getAttributeValue("name"));
processVariables.putAll(context.readJavaDelegate(fileScanner, listener.getCamundaClass(), element,
ElementChapter.ExecutionListener, KnownElementFieldType.Class, scopeId));
}
final CamundaScript script = listener.getCamundaScript();
if (script != null && script.getCamundaScriptFormat() != null
&& script.getCamundaScriptFormat().equals(ConfigConstants.GROOVY)) {
// inline script or external file?
final String inlineScript = script.getTextContent();
if (inlineScript != null && inlineScript.trim().length() > 0) {
processVariables.putAll(
ResourceFileReader.searchProcessVariablesInCode(element, ElementChapter.ExecutionListener,
KnownElementFieldType.InlineScript, null, scopeId, inlineScript));
} else {
final String resourcePath = script.getCamundaResource();
if (resourcePath != null) {
processVariables.putAll(getVariablesFromGroovyScript(resourcePath, element,
ElementChapter.ExecutionListener, KnownElementFieldType.ExternalScript, scopeId));
}
}
}
}
return processVariables;
}
/**
* Get process variables from task listeners
*
* @param context JavaReaderContext
*
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @param extensionElements
* ExtensionElements
* @param scopeId
* ScopeId
* @return variables
*/
private LinkedHashMap getVariablesFromTaskListener(
final JavaReaderContext context, final FileScanner fileScanner, final BpmnElement element,
final ExtensionElements extensionElements, final String scopeId) {
final LinkedHashMap processVariables = new LinkedHashMap();
List listenerList = extensionElements.getElementsQuery()
.filterByType(CamundaTaskListener.class).list();
for (final CamundaTaskListener listener : listenerList) {
final String l_expression = listener.getCamundaExpression();
if (l_expression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, l_expression, element,
ElementChapter.TaskListener, KnownElementFieldType.Expression, scopeId));
}
final String l_delegateExpression = listener.getCamundaDelegateExpression();
if (l_delegateExpression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, l_delegateExpression, element,
ElementChapter.TaskListener, KnownElementFieldType.DelegateExpression, scopeId));
}
processVariables
.putAll(new JavaReaderRegex().getVariablesFromJavaDelegate(fileScanner, listener.getCamundaClass(),
element, ElementChapter.TaskListener, KnownElementFieldType.Class, scopeId));
final CamundaScript script = listener.getCamundaScript();
if (script != null && script.getCamundaScriptFormat() != null
&& script.getCamundaScriptFormat().equals(ConfigConstants.GROOVY)) {
// inline script or external file?
final String inlineScript = script.getTextContent();
if (inlineScript != null && inlineScript.trim().length() > 0) {
processVariables.putAll(
ResourceFileReader.searchProcessVariablesInCode(element, ElementChapter.TaskListener,
KnownElementFieldType.InlineScript, null, scopeId, inlineScript));
} else {
final String resourcePath = script.getCamundaResource();
if (resourcePath != null) {
processVariables.putAll(getVariablesFromGroovyScript(resourcePath, element,
ElementChapter.TaskListener, KnownElementFieldType.ExternalScript, scopeId));
}
}
}
}
return processVariables;
}
/**
* Get process variables from form fields (user tasks)
*
* @param element
* BpmnElement
* @param extensionElements
* ExtensionElements
* @param scopeElementId
* ScopeElementId
* @return variables
*/
private LinkedHashMap getVariablesFromFormData(final BpmnElement element,
final ExtensionElements extensionElements, final String scopeElementId) {
final LinkedHashMap processVariables = new LinkedHashMap();
final Query formDataQuery = extensionElements.getElementsQuery()
.filterByType(CamundaFormData.class);
if (formDataQuery.count() > 0) {
final CamundaFormData formData = formDataQuery.singleResult();
if (formData != null) {
final Collection formFields = formData.getCamundaFormFields();
for (final CamundaFormField field : formFields) {
processVariables.put(field.getCamundaId(),
new ProcessVariableOperation(field.getCamundaId(), element, ElementChapter.FormData,
KnownElementFieldType.FormField, null, VariableOperation.WRITE, scopeElementId));
}
}
}
return processVariables;
}
/**
* Get process variables from camunda input/output associations (call
* activities)
*
* @param element
* BpmnElement
* @param extensionElements
* ExtensionElements
* @param scopeId
* ScopeId
* @return variables
*/
private LinkedHashMap searchVariablesInInputOutputExtensions(
final BpmnElement element, final ExtensionElements extensionElements, final String scopeId) {
final LinkedHashMap processVariables = new LinkedHashMap();
final BaseElement baseElement = element.getBaseElement();
if (baseElement instanceof CallActivity) {
final List inputAssociations = extensionElements.getElementsQuery().filterByType(CamundaIn.class)
.list();
for (final CamundaIn inputAssociation : inputAssociations) {
final String source = inputAssociation.getCamundaSource();
if (source != null && !source.isEmpty()) {
processVariables.put(source, new ProcessVariableOperation(source, element, ElementChapter.InputData,
KnownElementFieldType.CamundaIn, null, VariableOperation.READ, scopeId));
}
}
final List outputAssociations = extensionElements.getElementsQuery()
.filterByType(CamundaOut.class).list();
for (final CamundaOut outputAssociation : outputAssociations) {
final String target = outputAssociation.getCamundaTarget();
if (target != null && !target.isEmpty()) {
processVariables.put(target,
new ProcessVariableOperation(target, element, ElementChapter.OutputData,
KnownElementFieldType.CamundaOut, null, VariableOperation.WRITE, scopeId));
}
}
}
return processVariables;
}
/**
* Get process variables from sequence flow conditions
*
* @param context
* JavaReaderContext
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @return variables
*/
private LinkedHashMap searchVariablesFromSequenceFlow(
final JavaReaderContext context, final FileScanner fileScanner, final BpmnElement element) {
final LinkedHashMap variables = new LinkedHashMap();
final BaseElement baseElement = element.getBaseElement();
if (baseElement instanceof SequenceFlow) {
final SequenceFlow flow = (SequenceFlow) baseElement;
BpmnModelElementInstance scopeElement = flow.getScope();
String scopeId = null;
if (scopeElement != null) {
scopeId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
final ConditionExpression expression = flow.getConditionExpression();
if (expression != null) {
if (expression.getLanguage() != null && expression.getLanguage().equals(ConfigConstants.GROOVY)) {
// inline script or external file?
final String inlineScript = expression.getTextContent();
if (inlineScript != null && inlineScript.trim().length() > 0) {
variables
.putAll(ResourceFileReader.searchProcessVariablesInCode(element, ElementChapter.Details,
KnownElementFieldType.InlineScript, scopeId, null, inlineScript));
} else {
final String resourcePath = expression.getCamundaResource();
if (resourcePath != null) {
variables.putAll(getVariablesFromGroovyScript(resourcePath, element, ElementChapter.Details,
KnownElementFieldType.ExternalScript, scopeId));
}
}
} else {
if (expression.getTextContent().trim().length() > 0) {
variables.putAll(findVariablesInExpression(context, fileScanner, expression.getTextContent(),
element, ElementChapter.Details, KnownElementFieldType.Expression, scopeId));
}
}
}
}
return variables;
}
/**
* Analyse all types of tasks for process variables
*
* @param context
* JavaReaderContext
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @return variables
*/
private Map getVariablesFromTask(final JavaReaderContext context,
final FileScanner fileScanner, final BpmnElement element) {
final Map processVariables = new HashMap();
final BaseElement baseElement = element.getBaseElement();
BpmnModelElementInstance scopeElement = baseElement.getScope();
String scopeId = null;
if (scopeElement != null) {
scopeId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
if (baseElement instanceof ServiceTask || baseElement instanceof SendTask
|| baseElement instanceof BusinessRuleTask) {
final String t_expression = baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.ATTR_EX);
if (t_expression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, t_expression, element,
ElementChapter.Details, KnownElementFieldType.Expression, scopeId));
}
final String t_delegateExpression = baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.ATTR_DEL);
if (t_delegateExpression != null) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, t_delegateExpression, element,
ElementChapter.Details, KnownElementFieldType.DelegateExpression, scopeId));
}
final ArrayList t_fieldInjectionExpressions = bpmnScanner
.getFieldInjectionExpression(baseElement.getId());
if (t_fieldInjectionExpressions != null && !t_fieldInjectionExpressions.isEmpty()) {
for (String t_fieldInjectionExpression : t_fieldInjectionExpressions)
processVariables.putAll(findVariablesInExpression(context, fileScanner, t_fieldInjectionExpression,
element, ElementChapter.FieldInjections, KnownElementFieldType.Expression, scopeId));
}
final String t_resultVariable = baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.RESULT_VARIABLE);
if (t_resultVariable != null && t_resultVariable.trim().length() > 0) {
processVariables.put(t_resultVariable,
new ProcessVariableOperation(t_resultVariable, element, ElementChapter.Details,
KnownElementFieldType.ResultVariable, null, VariableOperation.WRITE, scopeId));
}
if (baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS, BpmnConstants.ATTR_CLASS) != null) {
processVariables.putAll(context.readJavaDelegate(fileScanner,
baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS, BpmnConstants.ATTR_CLASS),
element, ElementChapter.Details, KnownElementFieldType.Class, scopeId));
}
if (baseElement instanceof BusinessRuleTask) {
final String t_decisionRef = baseElement.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.DECISIONREF);
if (t_decisionRef != null && t_decisionRef.trim().length() > 0 && decisionRefToPathMap != null) {
final String fileName = decisionRefToPathMap.get(t_decisionRef);
if (fileName != null) {
processVariables.putAll(readDmnFile(t_decisionRef, fileName, element, ElementChapter.Details,
KnownElementFieldType.DMN, scopeId));
}
}
}
} else if (baseElement instanceof UserTask) {
final UserTask userTask = (UserTask) baseElement;
final String assignee = userTask.getCamundaAssignee();
if (assignee != null)
processVariables.putAll(findVariablesInExpression(context, fileScanner, assignee, element,
ElementChapter.Details, KnownElementFieldType.Assignee, scopeId));
final String candidateUsers = userTask.getCamundaCandidateUsers();
if (candidateUsers != null)
processVariables.putAll(findVariablesInExpression(context, fileScanner, candidateUsers, element,
ElementChapter.Details, KnownElementFieldType.CandidateUsers, scopeId));
final String candidateGroups = userTask.getCamundaCandidateGroups();
if (candidateGroups != null)
processVariables.putAll(findVariablesInExpression(context, fileScanner, candidateGroups, element,
ElementChapter.Details, KnownElementFieldType.CandidateGroups, scopeId));
final String dueDate = userTask.getCamundaDueDate();
if (dueDate != null)
processVariables.putAll(findVariablesInExpression(context, fileScanner, dueDate, element,
ElementChapter.Details, KnownElementFieldType.DueDate, scopeId));
final String followUpDate = userTask.getCamundaFollowUpDate();
if (followUpDate != null)
processVariables.putAll(findVariablesInExpression(context, fileScanner, followUpDate, element,
ElementChapter.Details, KnownElementFieldType.FollowUpDate, scopeId));
} else if (baseElement instanceof ScriptTask) {
// Examine script task for process variables
final ScriptTask scriptTask = (ScriptTask) baseElement;
if (scriptTask.getScriptFormat() != null && scriptTask.getScriptFormat().equals(ConfigConstants.GROOVY)) {
// inline script or external file?
final Script script = scriptTask.getScript();
if (script != null && script.getTextContent() != null && script.getTextContent().trim().length() > 0) {
processVariables
.putAll(ResourceFileReader.searchProcessVariablesInCode(element, ElementChapter.Details,
KnownElementFieldType.InlineScript, null, scopeId, script.getTextContent()));
} else {
final String resourcePath = scriptTask.getCamundaResource();
if (resourcePath != null) {
processVariables.putAll(getVariablesFromGroovyScript(resourcePath, element,
ElementChapter.Details, KnownElementFieldType.ExternalScript, scopeId));
}
}
}
String resultVariable = scriptTask.getCamundaResultVariable();
if (resultVariable != null && resultVariable.trim().length() > 0) {
processVariables.put(resultVariable,
new ProcessVariableOperation(resultVariable, element, ElementChapter.Details,
KnownElementFieldType.ResultVariable, null, VariableOperation.WRITE, scopeId));
}
} else if (baseElement instanceof CallActivity) {
final CallActivity callActivity = (CallActivity) baseElement;
final String calledElement = callActivity.getCalledElement();
if (calledElement != null && calledElement.trim().length() > 0) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, calledElement, element,
ElementChapter.Details, KnownElementFieldType.CalledElement, scopeId));
}
final String caseRef = callActivity.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.CASEREF);
if (caseRef != null && caseRef.trim().length() > 0) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, caseRef, element,
ElementChapter.Details, KnownElementFieldType.CaseRef, scopeId));
}
}
// Check multi instance attributes
processVariables.putAll(searchVariablesInMultiInstanceTask(context, fileScanner, element));
return processVariables;
}
/**
* Examine multi instance tasks for process variables
*
* @param context
* JavaReaderContext
* @param fileScanner
* FileScanner
* @param element
* BpmnElement
* @return variables
*/
private Map searchVariablesInMultiInstanceTask(final JavaReaderContext context,
final FileScanner fileScanner, final BpmnElement element) {
final Map processVariables = new HashMap();
final BaseElement baseElement = element.getBaseElement();
BpmnModelElementInstance scopeElement = baseElement.getScope();
String scopeId = null;
if (scopeElement != null) {
scopeId = scopeElement.getAttributeValue(BpmnConstants.ATTR_ID);
}
final ModelElementInstance loopCharacteristics = baseElement
.getUniqueChildElementByType(LoopCharacteristics.class);
if (loopCharacteristics != null) {
final String collectionName = loopCharacteristics.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.COLLECTION);
if (collectionName != null && collectionName.trim().length() > 0) {
processVariables.put(collectionName,
new ProcessVariableOperation(collectionName, element, ElementChapter.MultiInstance,
KnownElementFieldType.CollectionElement, null, VariableOperation.READ, scopeId));
}
final String elementVariable = loopCharacteristics.getAttributeValueNs(BpmnModelConstants.CAMUNDA_NS,
BpmnConstants.ELEMENT_VARIABLE);
if (elementVariable != null && elementVariable.trim().length() > 0) {
processVariables.put(elementVariable,
new ProcessVariableOperation(elementVariable, element, ElementChapter.MultiInstance,
KnownElementFieldType.ElementVariable, null, VariableOperation.READ, scopeId));
}
final ModelElementInstance loopCardinality = loopCharacteristics
.getUniqueChildElementByType(LoopCardinality.class);
if (loopCardinality != null) {
final String cardinality = loopCardinality.getTextContent();
if (cardinality != null && cardinality.trim().length() > 0) {
processVariables.putAll(findVariablesInExpression(context, fileScanner, cardinality, element,
ElementChapter.MultiInstance, KnownElementFieldType.LoopCardinality, scopeId));
}
}
final ModelElementInstance completionCondition = loopCharacteristics
.getUniqueChildElementByType(CompletionCondition.class);
if (completionCondition != null) {
final String completionConditionExpression = completionCondition.getTextContent();
if (completionConditionExpression != null && completionConditionExpression.trim().length() > 0) {
processVariables.putAll(
findVariablesInExpression(context, fileScanner, completionConditionExpression, element,
ElementChapter.MultiInstance, KnownElementFieldType.CompletionCondition, scopeId));
}
}
}
return processVariables;
}
/**
* Checks an external groovy script for process variables (read/write).
*
* @param groovyFile
* Groovy File
* @param element
* BpmnElement
* @param chapter
* ElementChapter
* @param fieldType
* KnownElementFieldType
* @param scopeId
* ScopeId
* @return variables
*/
private Map getVariablesFromGroovyScript(final String groovyFile,
final BpmnElement element, final ElementChapter chapter, final KnownElementFieldType fieldType,
final String scopeId) {
final Map variables = ResourceFileReader.readResourceFile(groovyFile, element,
chapter, fieldType, scopeId);
return variables;
}
/**
* Scans a dmn file for process variables
*
* @param decisionId
* DecisionId
* @param fileName
* File Name
* @param element
* BpmnElement
* @param chapter
* ElementChapter
* @param fieldType
* KnownElementFieldType
* @param scopeId
* ScopeID
* @return
*/
private Map readDmnFile(final String decisionId, final String fileName,
final BpmnElement element, final ElementChapter chapter, final KnownElementFieldType fieldType,
final String scopeId) {
final Map variables = new HashMap();
if (fileName != null && fileName.trim().length() > 0) {
final InputStream resource = RuntimeConfig.getInstance().getClassLoader().getResourceAsStream(fileName);
if (resource != null) {
// parse dmn model
final DmnModelInstance modelInstance = Dmn.readModelFromStream(resource);
final Decision decision = modelInstance.getModelElementById(decisionId);
final Collection inputExpressions = decision.getModelInstance()
.getModelElementsByType(InputExpression.class);
for (final InputExpression inputExpression : inputExpressions) {
final Text variable = inputExpression.getText();
variables.put(variable.getTextContent(), new ProcessVariableOperation(variable.getTextContent(),
element, chapter, fieldType, fileName, VariableOperation.READ, scopeId));
}
final Collection