Skip to content

Handle candiate groups and users user task activity #2859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static java.util.stream.Collectors.toList;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.UserTask;
Expand Down Expand Up @@ -301,23 +303,71 @@ protected void handleAssignments(TaskService taskService, String assignee, Strin
List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution,
ProcessEngineConfigurationImpl processEngineConfiguration) {

if (StringUtils.isNotEmpty(assignee)) {
Object assigneeExpressionValue = expressionManager.createExpression(assignee).getValue(execution);
String assigneeValue = null;
if (assigneeExpressionValue != null) {
assigneeValue = assigneeExpressionValue.toString();
handleAssignee(assignee, expressionManager, execution, processEngineConfiguration, task);
handleOwner(owner, expressionManager, execution, processEngineConfiguration, task);
handleCandidateGroups(candidateGroups, expressionManager, execution, processEngineConfiguration, task);
handleCandidateUsers(candidateUsers, expressionManager, execution, processEngineConfiguration, task);

if (userTask.getCustomUserIdentityLinks() != null && !userTask.getCustomUserIdentityLinks().isEmpty()) {

List<IdentityLinkEntity> customIdentityLinkEntities = new ArrayList<>();
for (String customUserIdentityLinkType : userTask.getCustomUserIdentityLinks().keySet()) {
for (String userIdentityLink : userTask.getCustomUserIdentityLinks().get(customUserIdentityLinkType)) {
Expression idExpression = expressionManager.createExpression(userIdentityLink);
Object value = idExpression.getValue(execution);

Collection<String> userIds = extractCandidates(value, idExpression.getExpressionText());
for (String userId : userIds) {
IdentityLinkEntity identityLinkEntity = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().createTaskIdentityLink(task.getId(), userId, null, customUserIdentityLinkType);
IdentityLinkUtil.handleTaskIdentityLinkAddition(task, identityLinkEntity);
customIdentityLinkEntities.add(identityLinkEntity);
}
}
}

if (StringUtils.isNotEmpty(assigneeValue)) {
TaskHelper.changeTaskAssignee(task, assigneeValue);
if (!customIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
ObjectNode loggingNode = BpmnLoggingSessionUtil.fillBasicTaskLoggingData("Set task assignee value to " + assigneeValue, task, execution);
loggingNode.put("taskAssignee", assigneeValue);
LoggingSessionUtil.addLoggingData(LoggingSessionConstants.TYPE_USER_TASK_SET_ASSIGNEE, loggingNode, ScopeTypes.BPMN);
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_USER_IDENTITY_LINKS,
"Added " + customIdentityLinkEntities.size() + " custom user identity links to task", true,
customIdentityLinkEntities, task, execution);
}
}
}

if (userTask.getCustomGroupIdentityLinks() != null && !userTask.getCustomGroupIdentityLinks().isEmpty()) {

List<IdentityLinkEntity> customIdentityLinkEntities = new ArrayList<>();
for (String customGroupIdentityLinkType : userTask.getCustomGroupIdentityLinks().keySet()) {
for (String groupIdentityLink : userTask.getCustomGroupIdentityLinks().get(customGroupIdentityLinkType)) {

Expression idExpression = expressionManager.createExpression(groupIdentityLink);
Object value = idExpression.getValue(execution);
Collection<String> groupIds = extractCandidates(value, idExpression.getExpressionText());
for (String groupId : groupIds) {
IdentityLinkEntity identityLinkEntity = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().createTaskIdentityLink(
task.getId(), null, groupId, customGroupIdentityLinkType);
IdentityLinkUtil.handleTaskIdentityLinkAddition(task, identityLinkEntity);
customIdentityLinkEntities.add(identityLinkEntity);
}
}
}

if (!customIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_GROUP_IDENTITY_LINKS,
"Added " + customIdentityLinkEntities.size() + " custom group identity links to task", false,
customIdentityLinkEntities, task, execution);
}
}
}

}

protected void handleOwner(String owner, ExpressionManager expressionManager, DelegateExecution execution,
ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task) {

if (StringUtils.isNotEmpty(owner)) {
Object ownerExpressionValue = expressionManager.createExpression(owner).getValue(execution);
String ownerValue = null;
Expand All @@ -334,117 +384,116 @@ protected void handleAssignments(TaskService taskService, String assignee, Strin
}
}
}
}

protected void handleAssignee(String assignee, ExpressionManager expressionManager, DelegateExecution execution,
ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task){

if (StringUtils.isNotEmpty(assignee)) {
Object assigneeExpressionValue = expressionManager.createExpression(assignee).getValue(execution);
String assigneeValue = null;
if (assigneeExpressionValue != null) {
assigneeValue = assigneeExpressionValue.toString();
}

if (StringUtils.isNotEmpty(assigneeValue)) {
TaskHelper.changeTaskAssignee(task, assigneeValue);
if (processEngineConfiguration.isLoggingSessionEnabled()) {
ObjectNode loggingNode = BpmnLoggingSessionUtil.fillBasicTaskLoggingData("Set task assignee value to " + assigneeValue, task, execution);
loggingNode.put("taskAssignee", assigneeValue);
LoggingSessionUtil.addLoggingData(LoggingSessionConstants.TYPE_USER_TASK_SET_ASSIGNEE, loggingNode, ScopeTypes.BPMN);
}
}
}
}

protected void handleCandidateGroups(List<String> candidateGroups, ExpressionManager expressionManager, DelegateExecution execution,
ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task) {

if (candidateGroups != null && !candidateGroups.isEmpty()) {
List<IdentityLinkEntity> allIdentityLinkEntities = new ArrayList<>();
for (String candidateGroup : candidateGroups) {
Expression groupIdExpr = expressionManager.createExpression(candidateGroup);
Object value = groupIdExpr.getValue(execution);
if (value != null) {
Collection<String> candidates = extractCandidates(value);
Collection<String> candidates = extractCandidates(value, groupIdExpr.getExpressionText());
Collection<String> candidatesNormalized = normalizeCandidates(candidates);

if(isCandidateGroupsLimit(candidatesNormalized.size(), processEngineConfiguration.getUserTaskCandidateGroupsLimit())) {
throw new FlowableException("The number of groups after resolving expression exceeds the limit " + processEngineConfiguration.getUserTaskCandidateGroupsLimit() + " of allowed groups for a user task.");
}
List<IdentityLinkEntity> identityLinkEntities = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().addCandidateGroups(task.getId(), candidates);
.getIdentityLinkService().addCandidateGroups(task.getId(), candidatesNormalized);

if (identityLinkEntities != null && !identityLinkEntities.isEmpty()) {
IdentityLinkUtil.handleTaskIdentityLinkAdditions(task, identityLinkEntities);
allIdentityLinkEntities.addAll(identityLinkEntities);
}
}
}

if (!allIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_GROUP_IDENTITY_LINKS,
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_GROUP_IDENTITY_LINKS,
"Added " + allIdentityLinkEntities.size() + " candidate group identity links to task", false,
allIdentityLinkEntities, task, execution);
}
}
}
}

protected void handleCandidateUsers(List<String> candidateUsers, ExpressionManager expressionManager, DelegateExecution execution,
ProcessEngineConfigurationImpl processEngineConfiguration, TaskEntity task) {

if (candidateUsers != null && !candidateUsers.isEmpty()) {

List<IdentityLinkEntity> allIdentityLinkEntities = new ArrayList<>();
for (String candidateUser : candidateUsers) {
Expression userIdExpr = expressionManager.createExpression(candidateUser);
Object value = userIdExpr.getValue(execution);
if (value != null) {
Collection<String> candidates = extractCandidates(value);

Collection<String> candidates = extractCandidates(value, userIdExpr.getExpressionText());
Collection<String> candidatesNormalized = normalizeCandidates(candidates);

if(isCandidateUsersLimit(candidatesNormalized.size(), processEngineConfiguration.getUserTaskCandidateUsersLimit())) {
throw new FlowableException("The number of users after resolving expression exceeds the limit " + processEngineConfiguration.getUserTaskCandidateUsersLimit() + " of allowed users for a user task.");
}
List<IdentityLinkEntity> identityLinkEntities = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().addCandidateUsers(task.getId(), candidates);
.getIdentityLinkService().addCandidateUsers(task.getId(), candidatesNormalized);

if (identityLinkEntities != null && !identityLinkEntities.isEmpty()) {
IdentityLinkUtil.handleTaskIdentityLinkAdditions(task, identityLinkEntities);
allIdentityLinkEntities.addAll(identityLinkEntities);
}
}
}

if (!allIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_USER_IDENTITY_LINKS,
"Added " + allIdentityLinkEntities.size() + " candidate user identity links to task", true,
allIdentityLinkEntities, task, execution);
}
}
}

if (userTask.getCustomUserIdentityLinks() != null && !userTask.getCustomUserIdentityLinks().isEmpty()) {

List<IdentityLinkEntity> customIdentityLinkEntities = new ArrayList<>();
for (String customUserIdentityLinkType : userTask.getCustomUserIdentityLinks().keySet()) {
for (String userIdentityLink : userTask.getCustomUserIdentityLinks().get(customUserIdentityLinkType)) {
Expression idExpression = expressionManager.createExpression(userIdentityLink);
Object value = idExpression.getValue(execution);

Collection<String> userIds = extractCandidates(value);
for (String userId : userIds) {
IdentityLinkEntity identityLinkEntity = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().createTaskIdentityLink(task.getId(), userId, null, customUserIdentityLinkType);
IdentityLinkUtil.handleTaskIdentityLinkAddition(task, identityLinkEntity);
customIdentityLinkEntities.add(identityLinkEntity);
}
}
}

if (!customIdentityLinkEntities.isEmpty()) {
if (!allIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_USER_IDENTITY_LINKS,
"Added " + customIdentityLinkEntities.size() + " custom user identity links to task", true,
customIdentityLinkEntities, task, execution);
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_USER_IDENTITY_LINKS,
"Added " + allIdentityLinkEntities.size() + " candidate user identity links to task", true,
allIdentityLinkEntities, task, execution);
}
}
}
}

if (userTask.getCustomGroupIdentityLinks() != null && !userTask.getCustomGroupIdentityLinks().isEmpty()) {

List<IdentityLinkEntity> customIdentityLinkEntities = new ArrayList<>();
for (String customGroupIdentityLinkType : userTask.getCustomGroupIdentityLinks().keySet()) {
for (String groupIdentityLink : userTask.getCustomGroupIdentityLinks().get(customGroupIdentityLinkType)) {

Expression idExpression = expressionManager.createExpression(groupIdentityLink);
Object value = idExpression.getValue(execution);
Collection<String> groupIds = extractCandidates(value);
for (String groupId : groupIds) {
IdentityLinkEntity identityLinkEntity = processEngineConfiguration.getIdentityLinkServiceConfiguration()
.getIdentityLinkService().createTaskIdentityLink(
task.getId(), null, groupId, customGroupIdentityLinkType);
IdentityLinkUtil.handleTaskIdentityLinkAddition(task, identityLinkEntity);
customIdentityLinkEntities.add(identityLinkEntity);
}
}
}
public boolean isCandidateUsersLimit(int candidateUsersSize, int userTaskCandidateUsersLimit) {
return userTaskCandidateUsersLimit >= 0 && candidateUsersSize > userTaskCandidateUsersLimit;
}

if (!customIdentityLinkEntities.isEmpty()) {
if (processEngineConfiguration.isLoggingSessionEnabled()) {
BpmnLoggingSessionUtil.addTaskIdentityLinkData(LoggingSessionConstants.TYPE_USER_TASK_SET_GROUP_IDENTITY_LINKS,
"Added " + customIdentityLinkEntities.size() + " custom group identity links to task", false,
customIdentityLinkEntities, task, execution);
}
}
}
public boolean isCandidateGroupsLimit(int candidateGroupsSize, int userTaskCandidateGroupsLimit) {
return userTaskCandidateGroupsLimit >= 0 && candidateGroupsSize > userTaskCandidateGroupsLimit;
}

public Collection<String> normalizeCandidates(Collection<String> candidates) {
Stream<String> candidatesNormalized = candidates.stream().map(String::trim).filter(candidate -> !candidate.isEmpty()).distinct();
return candidatesNormalized.collect(toList());
}

protected Collection<String> extractCandidates(Object value) {
public Collection<String> extractCandidates(Object value, String expressionText) {
handleUnsupportedType(value, expressionText);
if (value instanceof Collection) {
return (Collection<String>) value;
} else if (value instanceof ArrayNode) {
Expand All @@ -453,7 +502,6 @@ protected Collection<String> extractCandidates(Object value) {
for (JsonNode node : valueArrayNode) {
candidates.add(node.asText());
}

return candidates;
} else if (value != null) {
String str = value.toString();
Expand All @@ -465,7 +513,22 @@ protected Collection<String> extractCandidates(Object value) {
return Collections.emptyList();

}


protected void handleUnsupportedType(Object value, String expressionText) {
if (value instanceof Boolean) {
throw new FlowableIllegalArgumentException("Value of type boolean is not supported for expression '" + expressionText + "'.");
}
if (value instanceof Double) {
throw new FlowableIllegalArgumentException("Value of type double is not supported for expression '" + expressionText + "'.");
}
if (value instanceof Float) {
throw new FlowableIllegalArgumentException("Value of type float is not supported for expression '" + expressionText + "'.");
}
if (value instanceof ObjectNode) {
throw new FlowableIllegalArgumentException("Value of type objectNode is not supported for expression '" + expressionText + "'.");
}
}

protected String getAssigneeValue(UserTask userTask, MigrationContext migrationContext, ObjectNode taskElementProperties) {
if (migrationContext != null && migrationContext.getAssignee() != null) {
return migrationContext.getAssignee();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,8 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected boolean isExpressionCacheEnabled = true;
protected int expressionCacheSize = 4096;
protected int expressionTextLengthCacheLimit = -1; // negative value to have no max length
protected int userTaskCandidateGroupsLimit = -1; // By default, no limit
protected int userTaskCandidateUsersLimit = -1; // By default, no limit

protected BusinessCalendarManager businessCalendarManager;

Expand Down Expand Up @@ -3425,6 +3427,22 @@ public ProcessEngineConfigurationImpl setExpressionTextLengthCacheLimit(int expr
return this;
}

public int getUserTaskCandidateGroupsLimit() {
return userTaskCandidateGroupsLimit;
}

public void setUserTaskCandidateGroupsLimit(int userTaskCandidateGroupsLimit) {
this.userTaskCandidateGroupsLimit = userTaskCandidateGroupsLimit;
}

public int getUserTaskCandidateUsersLimit() {
return userTaskCandidateUsersLimit;
}

public void setUserTaskCandidateUsersLimit(int userTaskCandidateUsersLimit) {
this.userTaskCandidateUsersLimit = userTaskCandidateUsersLimit;
}

public BusinessCalendarManager getBusinessCalendarManager() {
return businessCalendarManager;
}
Expand Down
Loading