Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.xlrit.gears.server.graphql.TaskResolver Maven / Gradle / Ivy
package com.xlrit.gears.server.graphql;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import com.xlrit.gears.base.choice.Choice;
import com.xlrit.gears.base.choice.Choices;
import com.xlrit.gears.base.util.Range;
import com.xlrit.gears.engine.facade.EngineFacade;
import com.xlrit.gears.engine.facade.InProgress;
import com.xlrit.gears.engine.flowable.CustomTaskListQuery;
import com.xlrit.gears.engine.security.AuthManager;
import com.fasterxml.jackson.databind.JsonNode;
import graphql.schema.DataFetchingEnvironment;
import lombok.RequiredArgsConstructor;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.common.engine.impl.service.CommonEngineServiceImpl;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.service.impl.TaskQueryProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.multipart.MultipartFile;
import static com.xlrit.gears.engine.util.EngineUtils.requireFound;
@Controller
@RequiredArgsConstructor
public class TaskResolver {
private static final Logger LOG = LoggerFactory.getLogger(TaskResolver.class);
private final TaskService taskService;
private final RuntimeService runtimeService;
private final AuthManager authManager;
private final EngineFacade engineFacade;
// === queries === //
@PreAuthorize("isAuthenticated()")
@QueryMapping
public Task task(@Argument String id, DataFetchingEnvironment env) {
TaskQuery query = taskService.createTaskQuery().taskId(id);
if (env.getSelectionSet().contains("error")) {
query.includeTaskLocalVariables();
}
return query.singleResult();
}
@QueryMapping
public Choice choice(@Argument String taskId, @Argument String processDefinitionId, @Argument String path, @Argument String value, @Argument JsonNode values) {
LOG.info("Returning choice for taskId={}, processDefinitionId={}, path={}, value={}, values={}", taskId, processDefinitionId, path, value, values);
Choices choices = engineFacade.getChoices(taskId, processDefinitionId, path, values);
return choices == null ? null : choices.find(value).orElse(null);
}
@QueryMapping
public List extends Choice> choices(@Argument String taskId, @Argument String processDefinitionId, @Argument String path, @Argument String filter, @Argument Range range, @Argument JsonNode values) {
LOG.info("Returning choices for taskId={}, processDefinitionId={}, path={}, filter={}, range={}, values={}", taskId, processDefinitionId, path, filter, range, values);
Choices choices = engineFacade.getChoices(taskId, processDefinitionId, path, values);
return choices == null ? Collections.emptyList() : choices.items(filter, range).collect(Collectors.toList());
}
@PreAuthorize("hasRole('admin')")
@QueryMapping
public List allTasks(@Argument String filter, @Argument Range range) {
return listTasks(filter, range, query -> {});
}
@QueryMapping
public long allTasksCount(@Argument String filter) {
if (!authManager.isAdmin()) return -1L;
return countTasks(filter, query -> {});
}
@QueryMapping
public List assignedTasks(@Argument String filter, @Argument Range range) {
String currentUserId = authManager.getCurrentUserId();
if (currentUserId == null) return Collections.emptyList();
return listTasks(filter, range, query -> query.assignee(currentUserId));
}
@QueryMapping
public long assignedTasksCount(@Argument String filter) {
String currentUserId = authManager.getCurrentUserId();
if (currentUserId == null) return 0L;
return countTasks(filter, query -> query.assignee(currentUserId));
}
@QueryMapping
public List groupTasks(@Argument String filter, @Argument Range range) {
Set currentUserRoleNames = authManager.getCurrentUserRoleNames();
if (currentUserRoleNames == null || currentUserRoleNames.isEmpty()) return Collections.emptyList();
return listTasks(filter, range, query -> query.candidateGroups(currentUserRoleNames).assigned(false));
}
@QueryMapping
public long groupTasksCount(@Argument String filter) {
Set currentUserRoleNames = authManager.getCurrentUserRoleNames();
if (currentUserRoleNames == null || currentUserRoleNames.isEmpty()) return 0L;
return countTasks(filter, query -> query.candidateGroups(currentUserRoleNames).assigned(false));
}
@QueryMapping
public List transferableTasks(@Argument String filter, @Argument Range range) {
String currentUserId = authManager.getCurrentUserId();
Set currentUserRoleNames = authManager.getCurrentUserRoleNames();
if (currentUserId == null || currentUserRoleNames == null || currentUserRoleNames.isEmpty()) return Collections.emptyList();
return listTasks(filter, range, query -> query.candidateGroups(currentUserRoleNames).assigneeNot(currentUserId));
}
@QueryMapping
public long transferableTasksCount(@Argument String filter) {
String currentUserId = authManager.getCurrentUserId();
Set currentUserRoleNames = authManager.getCurrentUserRoleNames();
if (currentUserId == null || currentUserRoleNames == null || currentUserRoleNames.isEmpty()) return 0L;
return countTasks(filter, query -> query.candidateGroups(currentUserRoleNames).assigneeNot(currentUserId));
}
// === mutations === //
@PreAuthorize("isAuthenticated()")
@MutationMapping
public boolean claimTask(@Argument("id") String taskId) {
Objects.requireNonNull(taskId, "taskId must not be null");
engineFacade.claimTask(taskId);
return true;
}
@PreAuthorize("isAuthenticated()")
@MutationMapping
public boolean transferTask(@Argument("id") String taskId, @Argument("currentAssignee") String currentAssignee) {
Objects.requireNonNull(taskId, "taskId must not be null");
Objects.requireNonNull(currentAssignee, "currentAssignee must not be null");
engineFacade.transferTask(taskId, currentAssignee);
return true;
}
@PreAuthorize("isAuthenticated()")
@MutationMapping
public boolean saveTask(@Argument("id") String taskId, @Argument("values") JsonNode formValues, @Argument List files) {
Objects.requireNonNull(taskId, "taskId must not be null");
LOG.info("saveTask: id={}, values={}", taskId, formValues);
if (files != null && !files.isEmpty()) {
LOG.info("saveTask: received files");
for (MultipartFile file : files) {
LOG.info("- name={}, filename={}, type={}", file.getName(), file.getOriginalFilename(), file.getContentType());
}
}
engineFacade.saveTask(taskId, formValues, files);
return true;
}
/** GraphQL type is SubmitResult aka SubmitInProgress | ProcessInstance | ProcessInstanceEnded | InputErrors */
@PreAuthorize("isAuthenticated()")
@MutationMapping
public Object submitTask(@Argument String deploymentId, @Argument("id") String taskId, @Argument JsonNode values, @Argument List files, @Argument Long timeoutMillis) {
Objects.requireNonNull(taskId, "taskId must not be null");
if (timeoutMillis == null) timeoutMillis = Long.MAX_VALUE;
if (files != null && !files.isEmpty()) {
LOG.info("submitTask: received files");
for (MultipartFile file : files) {
LOG.info("- name={}, filename={}, type={}", file.getName(), file.getOriginalFilename(), file.getContentType());
}
}
Future futureResult = engineFacade.submitTaskAsync(deploymentId, taskId, values, files);
try {
LOG.debug("Getting futureResult with a timeout of {} seconds", timeoutMillis);
return futureResult.get(timeoutMillis, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e) {
return new InProgress(taskId);
}
catch (InterruptedException e) {
throw new RuntimeException("Submit task processing was interrupted", e);
}
catch (ExecutionException e) {
Throwable cause = e.getCause();
throw (cause instanceof RuntimeException ? (RuntimeException) cause : new RuntimeException("A checked exception occurred", cause));
}
}
@MutationMapping
@PreAuthorize("isAuthenticated()")
public ProcessInstance cancelTask(@Argument String deploymentId, @Argument("id") String taskId) {
Objects.requireNonNull(taskId, "taskId must not be null");
Task task = requireFound(
taskService.createTaskQuery().taskId(taskId).singleResult(),
"task", "id", taskId);
String instanceId = task.getProcessInstanceId();
String messageName = "cancel";
String executionId = task.getExecutionId();
LOG.info(
"cancelTask" +
": messageName=" + messageName +
", instanceId=" + instanceId +
", executionId=" + executionId +
", getTaskDefinitionId=" + task.getTaskDefinitionId() +
", getTaskDefinitionKey=" + task.getTaskDefinitionKey());
Execution cancelExecution =
runtimeService.createExecutionQuery()
.processInstanceId(instanceId)
.messageEventSubscriptionName(messageName)
.singleResult();
runtimeService.messageEventReceived(messageName, cancelExecution.getId());
return runtimeService.createProcessInstanceQuery()
.processInstanceId(instanceId)
.singleResult();
}
private List listTasks(String filter, Range range, Consumer customizer) {
return createCustomTaskListQuery()
.orderBy(TaskQueryProperty.CREATE_TIME).desc()
.filter(filter)
.customize(customizer)
.listPage(range.getStart(), range.getCount());
}
private long countTasks(String filter, Consumer customizer) {
return createCustomTaskListQuery()
.filter(filter)
.customize(customizer)
.count();
}
private CustomTaskListQuery createCustomTaskListQuery() {
CommandExecutor commandExecutor = ((CommonEngineServiceImpl>) taskService).getCommandExecutor();
return new CustomTaskListQuery(commandExecutor);
}
}