/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.casemgmt.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.drools.core.ClassObjectFilter; import org.jbpm.casemgmt.api.AdHocFragmentNotFoundException; import org.jbpm.casemgmt.api.CaseActiveException; import org.jbpm.casemgmt.api.CaseNotFoundException; import org.jbpm.casemgmt.api.CaseRuntimeDataService; import org.jbpm.casemgmt.api.CaseService; import org.jbpm.casemgmt.api.StageNotFoundException; import org.jbpm.casemgmt.api.auth.AuthorizationManager; import org.jbpm.casemgmt.api.auth.AuthorizationManager.ProtectedOperation; import org.jbpm.casemgmt.api.dynamic.TaskSpecification; import org.jbpm.casemgmt.api.generator.CaseIdGenerator; import org.jbpm.casemgmt.api.model.AdHocFragment; import org.jbpm.casemgmt.api.model.CaseDefinition; import org.jbpm.casemgmt.api.model.instance.CaseFileInstance; import org.jbpm.casemgmt.api.model.instance.CaseInstance; import org.jbpm.casemgmt.api.model.instance.CaseMilestoneInstance; import org.jbpm.casemgmt.api.model.instance.CaseRoleInstance; import org.jbpm.casemgmt.api.model.instance.CaseStageInstance; import org.jbpm.casemgmt.api.model.instance.CommentInstance; import org.jbpm.casemgmt.api.model.instance.CommentSortBy; import org.jbpm.casemgmt.impl.command.AddDataCaseFileInstanceCommand; import org.jbpm.casemgmt.impl.command.AddDynamicProcessCommand; import org.jbpm.casemgmt.impl.command.AddDynamicProcessToStageCommand; import org.jbpm.casemgmt.impl.command.AddDynamicTaskCommand; import org.jbpm.casemgmt.impl.command.AddDynamicTaskToStageCommand; import org.jbpm.casemgmt.impl.command.CancelCaseCommand; import org.jbpm.casemgmt.impl.command.CaseCommentCommand; import org.jbpm.casemgmt.impl.command.ModifyRoleAssignmentCommand; import org.jbpm.casemgmt.impl.command.RemoveDataCaseFileInstanceCommand; import org.jbpm.casemgmt.impl.command.ReopenCaseCommand; import org.jbpm.casemgmt.impl.command.StartCaseCommand; import org.jbpm.casemgmt.impl.dynamic.HumanTaskSpecification; import org.jbpm.casemgmt.impl.dynamic.WorkItemTaskSpecification; import org.jbpm.casemgmt.impl.event.CaseEventSupport; import org.jbpm.casemgmt.impl.model.instance.CaseFileInstanceImpl; import org.jbpm.casemgmt.impl.model.instance.CaseInstanceImpl; import org.jbpm.runtime.manager.impl.PerCaseRuntimeManager; import org.jbpm.services.api.DeploymentService; import org.jbpm.services.api.ProcessInstanceNotFoundException; import org.jbpm.services.api.ProcessService; import org.jbpm.services.api.RuntimeDataService; import org.jbpm.services.api.model.ProcessInstanceDesc; import org.jbpm.shared.services.impl.TransactionalCommandService; import org.jbpm.shared.services.impl.commands.QueryNameCommand; import org.kie.api.KieServices; import org.kie.api.command.KieCommands; import org.kie.api.runtime.manager.RuntimeManager; import org.kie.api.runtime.process.ProcessInstance; import org.kie.api.runtime.query.QueryContext; import org.kie.api.task.model.Group; import org.kie.api.task.model.OrganizationalEntity; import org.kie.api.task.model.User; import org.kie.internal.KieInternalServices; import org.kie.internal.identity.IdentityProvider; import org.kie.internal.process.CorrelationKeyFactory; import org.kie.internal.runtime.manager.context.CaseContext; import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext; import org.kie.internal.task.api.TaskModelFactory; import org.kie.internal.task.api.TaskModelProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CaseServiceImpl implements CaseService { private static final Logger logger = LoggerFactory.getLogger(CaseServiceImpl.class); private CorrelationKeyFactory correlationKeyFactory = KieInternalServices.Factory.get().newCorrelationKeyFactory(); private KieCommands commandsFactory = KieServices.Factory.get().getCommands(); private TaskModelFactory factory = TaskModelProvider.getFactory(); private CaseIdGenerator caseIdGenerator; private ProcessService processService; private RuntimeDataService runtimeDataService; private DeploymentService deploymentService; private CaseRuntimeDataService caseRuntimeDataService; private TransactionalCommandService commandService; private AuthorizationManager authorizationManager; private IdentityProvider identityProvider; private CaseEventSupport emptyCaseEventSupport = new CaseEventSupport(null, Collections.emptyList()); public void setProcessService(ProcessService processService) { this.processService = processService; } public void setRuntimeDataService(RuntimeDataService runtimeDataService) { this.runtimeDataService = runtimeDataService; } public void setDeploymentService(DeploymentService deploymentService) { this.deploymentService = deploymentService; } public void setCaseRuntimeDataService(CaseRuntimeDataService caseRuntimeDataService) { this.caseRuntimeDataService = caseRuntimeDataService; } public void setCaseIdGenerator(CaseIdGenerator caseIdGenerator) { this.caseIdGenerator = caseIdGenerator; } public void setCommandService(TransactionalCommandService commandService) { this.commandService = commandService; } public void setAuthorizationManager(AuthorizationManager authorizationManager) { this.authorizationManager = authorizationManager; } public void setIdentityProvider(IdentityProvider identityProvider) { this.identityProvider = identityProvider; this.emptyCaseEventSupport = new CaseEventSupport(identityProvider, Collections.emptyList()); } @Override public String startCase(String deploymentId, String caseDefinitionId) { return startCase(deploymentId, caseDefinitionId, null); } @Override public String startCase(String deploymentId, String caseDefinitionId, CaseFileInstance caseFile) { CaseDefinition caseDef = caseRuntimeDataService.getCase(deploymentId, caseDefinitionId); if (caseDef == null) { throw new CaseNotFoundException("Case definition " + caseDefinitionId + " not found"); } String caseId = caseIdGenerator.generate(caseDef.getIdentifierPrefix(), (caseFile == null ? new HashMap<>() : caseFile.getData())); logger.debug("Generated case id {} for case definition id {}", caseId, caseDefinitionId); if (caseFile == null) { caseFile = new CaseFileInstanceImpl(caseId, caseDefinitionId); ((CaseFileInstanceImpl)caseFile).setupRoles(caseDef.getCaseRoles()); logger.debug("CaseFile was not given, creating new empty one."); } else { ((CaseFileInstanceImpl)caseFile).setCaseId(caseId); logger.debug("CaseFile {} was given, associating it with case {}", caseFile, caseId); } //If owner is provided in the case file use that, otherwise default to current logged in user. boolean hasOwner = ((CaseFileInstanceImpl) caseFile).getAssignments().stream().anyMatch(role -> role.getRoleName().equals(AuthorizationManager.OWNER_ROLE)); if(hasOwner == false){ ((CaseFileInstanceImpl)caseFile).assignOwner(newUser(identityProvider.getName())); } processService.execute(deploymentId, CaseContext.get(caseId), new StartCaseCommand(identityProvider, caseId, deploymentId, caseDefinitionId, caseFile, processService)); return caseId; } @Override public CaseFileInstance getCaseFileInstance(String caseId) throws CaseNotFoundException { authorizationManager.checkAuthorization(caseId); ProcessInstanceDesc pi = verifyCaseIdExisted(caseId); return internalGetCaseFileInstance(caseId, pi.getDeploymentId()); } @Override public CaseInstance getCaseInstance(String caseId) throws CaseNotFoundException { return getCaseInstance(caseId, false, false, false, false); } @Override public CaseInstance getCaseInstance(String caseId, boolean withData, boolean withRoles, boolean withMilestones, boolean withStages) throws CaseNotFoundException { authorizationManager.checkAuthorization(caseId); CaseInstanceImpl caseInstance = (CaseInstanceImpl) caseRuntimeDataService.getCaseInstanceById(caseId); if (caseInstance.getStatus().equals(ProcessInstance.STATE_ACTIVE)) { if (withData) { CaseFileInstance caseFile = internalGetCaseFileInstance(caseId, caseInstance.getDeploymentId()); caseInstance.setCaseFile(caseFile); } if (withMilestones) { Collection<CaseMilestoneInstance> milestones = caseRuntimeDataService.getCaseInstanceMilestones(caseId, false, new org.kie.internal.query.QueryContext(0, 100)); caseInstance.setCaseMilestones(milestones); } if (withRoles) { Collection<CaseRoleInstance> roles = getCaseRoleAssignments(caseId); caseInstance.setCaseRoles(roles); } if (withStages) { Collection<CaseStageInstance> stages = caseRuntimeDataService.getCaseInstanceStages(caseId, true, new org.kie.internal.query.QueryContext(0, 100)); caseInstance.setCaseStages(stages); } return caseInstance; } else { return null; } } @Override public void cancelCase(String caseId) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.CANCEL_CASE); logger.debug("About to abort case {}", caseId); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new CancelCaseCommand(identityProvider, caseId, processService, runtimeDataService, false)); } @Override public void destroyCase(String caseId) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.DESTROY_CASE); logger.debug("About to destroy permanently case {}", caseId); ProcessInstanceDesc pi = verifyCaseIdExisted(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new CancelCaseCommand(identityProvider, caseId, processService, runtimeDataService, true)); } @Override public void reopenCase(String caseId, String deploymentId, String caseDefinitionId) throws CaseNotFoundException { reopenCase(caseId, deploymentId, caseDefinitionId, new HashMap<>()); } @Override public void reopenCase(String caseId, String deploymentId, String caseDefinitionId, Map<String, Object> data) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.REOPEN_CASE); ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId)); if (pi != null) { throw new CaseActiveException("Case with id " + caseId + " is still active and cannot be reopened"); } Map<String, Object> params = new HashMap<String, Object>(); params.put("caseId", caseId); params.put("maxResults", 1); List<Long> caseIdMapping = commandService.execute(new QueryNameCommand<List<Long>>("findCaseIdContextMapping", params)); if (caseIdMapping.isEmpty()) { throw new CaseNotFoundException("Case with id " + caseId + " was not found"); } logger.debug("About to reopen case {} by starting process instance {} from deployment {} with additional data {}", caseId, caseDefinitionId, deploymentId, data); processService.execute(deploymentId, CaseContext.get(caseId), new ReopenCaseCommand(identityProvider, caseId, deploymentId, caseDefinitionId, data, processService)); } /* * Dynamic operations on a case */ @Override public void addDynamicTask(String caseId, TaskSpecification taskSpecification) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_TASK_TO_CASE); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDynamicTaskCommand(identityProvider, caseId, taskSpecification.getNodeType(), pi.getId(), taskSpecification.getParameters())); } @Override public void addDynamicTask(Long processInstanceId, TaskSpecification taskSpecification) throws ProcessInstanceNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + processInstanceId + " or it's not active anymore"); } String caseId = pi.getCorrelationKey(); authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_TASK_TO_CASE); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new AddDynamicTaskCommand(identityProvider, caseId, taskSpecification.getNodeType(), pi.getId(), taskSpecification.getParameters())); } @Override public void addDynamicTaskToStage(String caseId, String stageId, TaskSpecification taskSpecification) throws CaseNotFoundException, StageNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_TASK_TO_CASE); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + pi.getId() + " or it's not active anymore"); } processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDynamicTaskToStageCommand(identityProvider, caseId, taskSpecification.getNodeType(), pi.getId(), stageId, taskSpecification.getParameters())); } @Override public void addDynamicTaskToStage(Long processInstanceId, String stageId, TaskSpecification taskSpecification) throws CaseNotFoundException, StageNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + processInstanceId + " or it's not active anymore"); } String caseId = pi.getCorrelationKey(); authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_TASK_TO_CASE); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new AddDynamicTaskToStageCommand(identityProvider, caseId, taskSpecification.getNodeType(), pi.getId(), stageId, taskSpecification.getParameters())); } @Override public Long addDynamicSubprocess(String caseId, String processId, Map<String, Object> parameters) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_PROCESS_TO_CASE); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + pi.getId() + " or it's not active anymore"); } return processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDynamicProcessCommand(identityProvider, caseId, pi.getId(), processId, parameters)); } @Override public Long addDynamicSubprocess(Long processInstanceId, String processId, Map<String, Object> parameters) throws CaseNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + processInstanceId + " or it's not active anymore"); } String caseId = pi.getCorrelationKey(); authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_PROCESS_TO_CASE); return processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new AddDynamicProcessCommand(identityProvider, caseId, pi.getId(), processId, parameters)); } @Override public Long addDynamicSubprocessToStage(String caseId, String stageId, String processId, Map<String, Object> parameters) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_PROCESS_TO_CASE); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); return processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDynamicProcessToStageCommand(identityProvider, caseId, pi.getId(), stageId, processId, parameters)); } @Override public Long addDynamicSubprocessToStage(Long processInstanceId, String stageId, String processId, Map<String, Object> parameters) throws CaseNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) { throw new ProcessInstanceNotFoundException("No process instance found with id " + processInstanceId + " or it's not active anymore"); } String caseId = pi.getCorrelationKey(); authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_PROCESS_TO_CASE); return processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(processInstanceId), new AddDynamicProcessToStageCommand(identityProvider, caseId, pi.getId(), stageId, processId, parameters)); } @Override public void triggerAdHocFragment(String caseId, String fragmentName, Object data) throws CaseNotFoundException { authorizationManager.checkAuthorization(caseId); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); triggerAdHocFragment(pi.getId(), fragmentName, data); } @Override public void triggerAdHocFragment(Long processInstanceId, String fragmentName, Object data) throws CaseNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceById(processInstanceId); internalTriggerAdHocFragment(pi, fragmentName, data); } /* * Case file data methods */ @Override public void addDataToCaseFile(String caseId, String name, Object value) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_DATA); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); Map<String, Object> parameters = new HashMap<>(); parameters.put(name, value); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDataCaseFileInstanceCommand(identityProvider, parameters)); } @Override public void addDataToCaseFile(String caseId, Map<String, Object> data) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.ADD_DATA); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new AddDataCaseFileInstanceCommand(identityProvider, data)); } @Override public void removeDataFromCaseFile(String caseId, String name) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.REMOVE_DATA); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new RemoveDataCaseFileInstanceCommand(identityProvider, Arrays.asList(name))); } @Override public void removeDataFromCaseFile(String caseId, List<String> variableNames) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.REMOVE_DATA); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new RemoveDataCaseFileInstanceCommand(identityProvider, variableNames)); } /* * Case role assignment methods */ @Override public void assignToCaseRole(String caseId, String role, OrganizationalEntity entity) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_ROLE_ASSIGNMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new ModifyRoleAssignmentCommand(identityProvider, role, entity, true)); } @Override public void removeFromCaseRole(String caseId, String role, OrganizationalEntity entity) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_ROLE_ASSIGNMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new ModifyRoleAssignmentCommand(identityProvider, role, entity, false)); } @Override public Collection<CaseRoleInstance> getCaseRoleAssignments(String caseId) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_ROLE_ASSIGNMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); CaseFileInstance caseFile = internalGetCaseFileInstance(caseId, pi.getDeploymentId()); return ((CaseFileInstanceImpl)caseFile).getAssignments(); } /* * Case comments methods */ @Override public Collection<CommentInstance> getCaseComments(String caseId, QueryContext queryContext) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_COMMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); CaseFileInstance caseFile = internalGetCaseFileInstance(caseId, pi.getDeploymentId()); return ((CaseFileInstanceImpl)caseFile).getComments(); } @Override public Collection<CommentInstance> getCaseComments(String caseId, CommentSortBy sortBy, QueryContext queryContext) throws CaseNotFoundException { authorizationManager.checkAuthorization(caseId); Collection<CommentInstance> comments = getCaseComments(caseId, queryContext); return comments.stream().sorted((o1, o2) -> { int result = 0; switch (sortBy) { case Date : result = o1.getCreatedAt().compareTo(o2.getCreatedAt()); break; case Author : result = o1.getAuthor().compareTo(o2.getAuthor()); break; } return result; }).collect(Collectors.toList()); } @Override public void addCaseComment(String caseId, String author, String comment) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_COMMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new CaseCommentCommand(identityProvider, author, comment)); } @Override public void updateCaseComment(String caseId, String commentId, String author, String text) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_COMMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new CaseCommentCommand(identityProvider, commentId, author, text)); } @Override public void removeCaseComment(String caseId, String commentId) throws CaseNotFoundException { authorizationManager.checkOperationAuthorization(caseId, ProtectedOperation.MODIFY_COMMENT); ProcessInstanceDesc pi = verifyCaseIdExists(caseId); processService.execute(pi.getDeploymentId(), ProcessInstanceIdContext.get(pi.getId()), new CaseCommentCommand(identityProvider, commentId)); } /* * new instances methods */ @Override public CaseFileInstance newCaseFileInstance(String deploymentId, String caseDefinition, Map<String, Object> data) { CaseDefinition def = caseRuntimeDataService.getCase(deploymentId, caseDefinition); CaseFileInstanceImpl caseFile = new CaseFileInstanceImpl(caseDefinition, data); caseFile.setupRoles(def.getCaseRoles()); return caseFile; } @Override public CaseFileInstance newCaseFileInstance(String deploymentId, String caseDefinition, Map<String, Object> data, Map<String, OrganizationalEntity> rolesAssignment) { CaseDefinition def = caseRuntimeDataService.getCase(deploymentId, caseDefinition); CaseFileInstanceImpl caseFile = new CaseFileInstanceImpl(caseDefinition, data); caseFile.setupRoles(def.getCaseRoles()); rolesAssignment.entrySet().stream().forEach(entry -> caseFile.assign(entry.getKey(), entry.getValue())); return caseFile; } @Override public TaskSpecification newHumanTaskSpec(String taskName, String description, String actorIds, String groupIds, Map<String, Object> parameters) { return new HumanTaskSpecification(taskName, actorIds, groupIds, description, parameters); } @Override public TaskSpecification newTaskSpec(String nodeType, String nodeName, Map<String, Object> parameters) { return new WorkItemTaskSpecification(nodeType, nodeName, parameters); } @Override public User newUser(String userId) { return factory.newUser(userId); } @Override public Group newGroup(String groupId) { return factory.newGroup(groupId); } /* * internal methods */ @SuppressWarnings("unchecked") protected CaseFileInstance internalGetCaseFileInstance(String caseId, String deploymentId) { logger.debug("Retrieving case file from working memory for case " + caseId); Collection<CaseFileInstance> caseFiles = (Collection<CaseFileInstance>) processService.execute(deploymentId, CaseContext.get(caseId), commandsFactory.newGetObjects(new ClassObjectFilter(CaseFileInstance.class))); if (caseFiles.size() == 0) { throw new CaseNotFoundException("Case with id " + caseId + " was not found"); } else if (caseFiles.size() == 1) { CaseFileInstance caseFile = caseFiles.iterator().next(); logger.debug("Single case file {} found in working memory", caseFile); return caseFile; } logger.warn("Multiple case files found in working memory (most likely not using PER_CASE strategy), trying to filter out..."); CaseFileInstance caseFile = caseFiles.stream() .filter(cf -> cf.getCaseId().equals(caseId)) .findFirst() .orElse(null); logger.warn("Case file {} after filtering {}", caseFile, (caseFile == null?"not found" : "found")); return caseFile; } protected void internalTriggerAdHocFragment(ProcessInstanceDesc pi, String fragmentName, Object data) throws CaseNotFoundException { CaseDefinition caseDef = caseRuntimeDataService.getCase(pi.getDeploymentId(), pi.getProcessId()); List<AdHocFragment> allFragments = new ArrayList<>(); if (caseDef.getAdHocFragments() != null) { allFragments.addAll(caseDef.getAdHocFragments()); } caseDef.getCaseStages().forEach(stage -> { if (stage.getAdHocFragments() != null) { allFragments.addAll(stage.getAdHocFragments()); } }); allFragments.stream() .filter(fragment -> fragment.getName().equals(fragmentName)) .findFirst() .orElseThrow(() -> new AdHocFragmentNotFoundException("AdHoc fragment '" + fragmentName + "' not found in case " + pi.getCorrelationKey())); processService.signalProcessInstance(pi.getId(), fragmentName, data); } /* * helper method */ protected ProcessInstanceDesc verifyCaseIdExists(String caseId) throws CaseNotFoundException { ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId)); if (pi == null) { throw new CaseNotFoundException("Case with id " + caseId + " was not found"); } return pi; } protected ProcessInstanceDesc verifyCaseIdExisted(String caseId) throws CaseNotFoundException { Collection<ProcessInstanceDesc> instances = runtimeDataService.getProcessInstancesByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId), new org.kie.api.runtime.query.QueryContext(0, 1)); if (instances.isEmpty()) { throw new CaseNotFoundException("Case with id " + caseId + " was not found"); } return instances.iterator().next(); } protected CaseEventSupport getCaseEventSupport(String deploymentId) { RuntimeManager runtimeManager = deploymentService.getRuntimeManager(deploymentId); if (runtimeManager instanceof PerCaseRuntimeManager) { CaseEventSupport caseEventSupport = (CaseEventSupport) ((PerCaseRuntimeManager) runtimeManager).getCaseEventSupport(); if (caseEventSupport != null) { return caseEventSupport; } } return emptyCaseEventSupport; } protected boolean isEmpty(Collection<?> data) { if (data == null || data.isEmpty()) { return true; } return false; } }