/* * 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. * * 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.kie.server.services.casemgmt; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jbpm.casemgmt.api.CaseRuntimeDataService; import org.jbpm.casemgmt.api.CaseService; import org.jbpm.casemgmt.api.dynamic.TaskSpecification; 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.CaseRoleInstance; import org.jbpm.casemgmt.api.model.instance.CommentInstance; import org.kie.api.task.model.OrganizationalEntity; import org.kie.internal.identity.IdentityProvider; import org.kie.internal.task.api.TaskModelFactory; import org.kie.internal.task.api.TaskModelProvider; import org.kie.server.api.KieServerConstants; import org.kie.server.api.model.cases.CaseComment; import org.kie.server.api.model.cases.CaseCommentList; import org.kie.server.api.model.cases.CaseFile; import org.kie.server.api.model.cases.CaseRoleAssignment; import org.kie.server.api.model.cases.CaseRoleAssignmentList; import org.kie.server.services.api.KieServerRegistry; import org.kie.server.services.casemgmt.locator.ByCaseIdContainerLocator; import org.kie.server.services.impl.locator.ContainerLocatorProvider; import org.kie.server.services.impl.marshal.MarshallerHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.kie.server.api.KieServerConstants.*; public class CaseManagementServiceBase { private static final Logger logger = LoggerFactory.getLogger(CaseManagementServiceBase.class); private IdentityProvider identityProvider; private CaseService caseService; private CaseRuntimeDataService caseRuntimeDataService; private MarshallerHelper marshallerHelper; private KieServerRegistry context; private TaskModelFactory taskModelFactory; private boolean bypassAuthUser = false; public CaseManagementServiceBase(CaseService caseService, CaseRuntimeDataService caseRuntimeDataService, KieServerRegistry context) { this.caseService = caseService; this.caseRuntimeDataService = caseRuntimeDataService; this.marshallerHelper = new MarshallerHelper(context); this.identityProvider = context.getIdentityProvider(); this.context = context; this.taskModelFactory = TaskModelProvider.getFactory(); this.bypassAuthUser = Boolean.parseBoolean(context.getConfig().getConfigItemValue(KieServerConstants.CFG_BYPASS_AUTH_USER, "false")); } protected String getUser(String queryParamUser) { if (bypassAuthUser) { return queryParamUser; } return identityProvider.getName(); } public String startCase(String containerId, String caseDefinitionId, String payload, String marshallingType) { containerId = context.getContainerId(containerId, ContainerLocatorProvider.get().getLocator()); CaseDefinition caseDef = caseRuntimeDataService.getCase(containerId, caseDefinitionId); if( caseDef == null ) { throw new IllegalStateException("Unable to find case '" + caseDefinitionId + "' in container " + containerId); } logger.debug("About to unmarshal case file from payload: '{}'", payload); CaseFile caseFile = marshallerHelper.unmarshal(containerId, payload, marshallingType, CaseFile.class); String caseId; if (caseFile == null) { logger.debug("Case file not given, starting case without case file"); caseId = caseService.startCase(containerId, caseDefinitionId); } else { logger.debug("Case file provided {}", caseFile); Map<String, OrganizationalEntity> roleAssignments = new HashMap<>(); if (caseFile.getUserAssignments() != null) { caseFile.getUserAssignments() .entrySet() .stream() .forEach(entry -> roleAssignments.put(entry.getKey(), taskModelFactory.newUser(entry.getValue()))); } if (caseFile.getGroupAssignments() != null) { caseFile.getGroupAssignments() .entrySet() .stream() .forEach( entry -> roleAssignments.put(entry.getKey(), taskModelFactory.newGroup(entry.getValue()))); } CaseFileInstance caseFileInstance = caseService.newCaseFileInstance(containerId, caseDefinitionId, caseFile.getData(), roleAssignments); caseId = caseService.startCase(containerId, caseDefinitionId, caseFileInstance); } logger.debug("New case instance started with case id {} for case definition {}", caseId, caseDefinitionId); // return response return marshallerHelper.marshal(containerId, marshallingType, caseId); } public String getCaseInstance(String containerId, String caseId, boolean withData, boolean withRoles, boolean withMilestones, boolean withStages, String marshallingType) { CaseInstance actualCaseInstance = caseService.getCaseInstance(caseId, withData, withRoles, withMilestones, withStages); org.kie.server.api.model.cases.CaseInstance caseInstance = ConvertUtils.transformCaseInstance(actualCaseInstance); if (withData) { caseInstance.setCaseFile(CaseFile.builder().data(actualCaseInstance.getCaseFile().getData()).build()); } if (withMilestones) { caseInstance.setMilestones(ConvertUtils.transformMilestones(actualCaseInstance.getCaseMilestones())); } if (withStages) { caseInstance.setStages(ConvertUtils.transformStages(actualCaseInstance.getCaseStages())); } if (withRoles) { caseInstance.setRoleAssignments(ConvertUtils.transformRoleAssignment(actualCaseInstance.getCaseRoles())); } logger.debug("About to marshal case instance with id '{}' {}", caseId, caseInstance); return marshallerHelper.marshal(containerId, marshallingType, caseInstance, new ByCaseIdContainerLocator(caseId)); } public void cancelCaseInstance(String containerId, String caseId, boolean destroy) { if (destroy) { logger.debug("Destroying case with id {} inside container {}", caseId, containerId); caseService.destroyCase(caseId); } else { logger.debug("Canceling case with id {} inside container {}", caseId, containerId); caseService.cancelCase(caseId); } } public void reopenCase(String caseId, String containerId, String caseDefinitionId, String payload, String marshallingType) { containerId = context.getContainerId(containerId, new ByCaseIdContainerLocator(caseId)); CaseDefinition caseDef = caseRuntimeDataService.getCase(containerId, caseDefinitionId); if( caseDef == null ) { throw new IllegalStateException("Unable to find case '" + caseDefinitionId + "' in container " + containerId); } logger.debug("About to unmarshal data from payload: '{}'", payload); Map<String, Object> data = marshallerHelper.unmarshal(containerId, payload, marshallingType, Map.class); caseService.reopenCase(caseId, containerId, caseDefinitionId, data); logger.debug("Case {} successfully reopened", caseId); } public String getCaseFileData(String containerId, String caseId, String marshallingType) { CaseFileInstance caseFileInstance = caseService.getCaseFileInstance(caseId); Map<String, Object> caseFileData = caseFileInstance.getData(); logger.debug("About to marshal case file data for case with id '{}' {}", caseId, caseFileData); return marshallerHelper.marshal(containerId, marshallingType, caseFileData, new ByCaseIdContainerLocator(caseId)); } public String getCaseFileDataByName(String containerId, String caseId, String name, String marshallingType) { CaseFileInstance caseFileInstance = caseService.getCaseFileInstance(caseId); Object caseFileData = caseFileInstance.getData(name); logger.debug("About to marshal case file data (name = {}) for case with id '{}' {}", name, caseId, caseFileData); return marshallerHelper.marshal(containerId, marshallingType, caseFileData, new ByCaseIdContainerLocator(caseId)); } public void putCaseFileData(String containerId, String caseId, String payload, String marshallingType) { logger.debug("About to unmarshal case file data from payload: '{}'", payload); Map<String, Object> caseFileData = marshallerHelper.unmarshal(containerId, payload, marshallingType, Map.class, new ByCaseIdContainerLocator(caseId)); logger.debug("Unmarshalled case file data {} for case with id '{}'", caseFileData, caseId); caseService.addDataToCaseFile(caseId, caseFileData); } public void putCaseFileDataByName(String containerId, String caseId, String name, String payload, String marshallingType) { logger.debug("About to unmarshal case file data from payload: '{}'", payload); Object caseFileData = marshallerHelper.unmarshal(containerId, payload, marshallingType, Object.class, new ByCaseIdContainerLocator(caseId)); logger.debug("Unmarshalled case file data {} for case with id '{}' will be stored under {}", caseFileData, caseId, name); caseService.addDataToCaseFile(caseId, name, caseFileData); } public void removeCaseFileDataByName(String containerId, String caseId, List<String> names) { logger.debug("Removing {} variables from case with id '{}'", names, caseId); caseService.removeDataFromCaseFile(caseId, names); } public void addDynamicTask(String containerId, String caseId, String stageId, String payload, String marshallingType) { logger.debug("About to unmarshal task specification content from payload: '{}'", payload); Map<String, Object> taskSpecificationMap = marshallerHelper.unmarshal(containerId, payload, marshallingType, Map.class, new ByCaseIdContainerLocator(caseId)); TaskSpecification taskSpecification = null; if (taskSpecificationMap == null || taskSpecificationMap.isEmpty()) { throw new IllegalArgumentException("Task specification must be given"); } String nodeType = (String) taskSpecificationMap.get(CASE_DYNAMIC_NODE_TYPE_PROP); if (nodeType != null) { logger.debug("Creating dynamic task of typ {} within case {}", nodeType, caseId); taskSpecification = caseService.newTaskSpec(nodeType, (String) taskSpecificationMap.get(CASE_DYNAMIC_NAME_PROP), (Map<String, Object>) taskSpecificationMap.get(CASE_DYNAMIC_DATA_PROP)); } else { logger.debug("Creating dynamic user task for case {}", caseId); taskSpecification = caseService.newHumanTaskSpec((String) taskSpecificationMap.get(CASE_DYNAMIC_NAME_PROP), (String) taskSpecificationMap.get(CASE_DYNAMIC_DESC_PROP), (String) taskSpecificationMap.get(CASE_DYNAMIC_ACTORS_PROP), (String) taskSpecificationMap.get(CASE_DYNAMIC_GROUPS_PROP), (Map<String, Object>) taskSpecificationMap.get(CASE_DYNAMIC_DATA_PROP)); } logger.debug("Complete task specification is '{}'", taskSpecification); if (stageId != null && !stageId.isEmpty()) { logger.debug("Adding dynamic task to stage {} within case {}", stageId, caseId); caseService.addDynamicTaskToStage(caseId, stageId, taskSpecification); } else { logger.debug("Adding dynamic task to case {}", caseId); caseService.addDynamicTask(caseId, taskSpecification); } } public void addDynamicSubprocess(String containerId, String caseId, String stageId, String processId, String payload, String marshallingType) { logger.debug("About to unmarshal process data from payload: '{}'", payload); Map<String, Object> subProcessParameters = marshallerHelper.unmarshal(containerId, payload, marshallingType, Map.class, new ByCaseIdContainerLocator(caseId)); logger.debug("SubProcess data '{}'", subProcessParameters); if (stageId != null && !stageId.isEmpty()) { logger.debug("Adding dynamic subprocess to stage {} within case {}", stageId, caseId); caseService.addDynamicSubprocessToStage(caseId, stageId, processId, subProcessParameters); } else { logger.debug("Adding dynamic subprocess to case {}", caseId); caseService.addDynamicSubprocess(caseId, processId, subProcessParameters); } } public void triggerAdHocNode(String containerId, String caseId, String stageId, String adHocName, String payload, String marshallingType) { logger.debug("About to unmarshal task data from payload: '{}'", payload); Map<String, Object> adHocTaskData = marshallerHelper.unmarshal(containerId, payload, marshallingType, Map.class, new ByCaseIdContainerLocator(caseId)); logger.debug("AdHoc task {} will be triggered with data = {}", adHocName, adHocTaskData); if (stageId != null && !stageId.isEmpty()) { // todo add support for trigger within given stage } else { caseService.triggerAdHocFragment(caseId, adHocName, adHocTaskData); } } public CaseRoleAssignmentList getRoleAssignment(String containerId, String caseId) { Collection<CaseRoleInstance> caseRoleInstances = caseService.getCaseRoleAssignments(caseId); logger.debug("Roles assignments for case {} are {}", caseId, caseRoleInstances); List<CaseRoleAssignment> caseRoles = ConvertUtils.transformRoleAssignment(caseRoleInstances); CaseRoleAssignmentList caseRolesList = new CaseRoleAssignmentList(caseRoles); return caseRolesList; } public void assignToRole(String containerId, String caseId, String roleName, String user, String group) { OrganizationalEntity entity = null; if (user != null && !user.isEmpty()) { entity = taskModelFactory.newUser(user); logger.debug("Assigning user {} to role {} in case {}", user, roleName, caseId); caseService.assignToCaseRole(caseId, roleName, entity); } if (group != null && !group.isEmpty()) { entity = taskModelFactory.newGroup(group); logger.debug("Assigning group {} to role {} in case {}", group, roleName, caseId); caseService.assignToCaseRole(caseId, roleName, entity); } } public void removeFromRole(String containerId, String caseId, String roleName, String user, String group) { OrganizationalEntity entity = null; if (user != null && !user.isEmpty()) { entity = taskModelFactory.newUser(user); logger.debug("Removing user {} from role {} in case {}", user, roleName, caseId); caseService.removeFromCaseRole(caseId, roleName, entity); } if (group != null && !group.isEmpty()) { entity = taskModelFactory.newGroup(group); logger.debug("Removing group {} from role {} in case {}", group, roleName, caseId); caseService.removeFromCaseRole(caseId, roleName, entity); } } public void addCommentToCase(String containerId, String caseId, String author, String comment, String marshallingType) { author = getUser(author); String actualComment = marshallerHelper.unmarshal(containerId, comment, marshallingType, String.class, new ByCaseIdContainerLocator(caseId)); logger.debug("Adding comment to case {} by {} with text '{}'", caseId, author, actualComment); caseService.addCaseComment(caseId, author, actualComment); } public void updateCommentInCase(String containerId, String caseId, String commentId, String author, String comment, String marshallingType) { author = getUser(author); String actualComment = marshallerHelper.unmarshal(containerId, comment, marshallingType, String.class, new ByCaseIdContainerLocator(caseId)); logger.debug("Updating comment {} in case {} by {} with text '{}'", commentId, caseId, author, actualComment); caseService.updateCaseComment(caseId, commentId, author, actualComment); } public void removeCommentFromCase(String containerId, String caseId, String commentId) { logger.debug("Removing comment with id {} from case {}", commentId, caseId); caseService.removeCaseComment(caseId, commentId); } public CaseCommentList getComments(String containerId, String caseId, Integer page, Integer pageSize) { Collection<CommentInstance> caseComments = caseService.getCaseComments(caseId, ConvertUtils.buildQueryContext(page, pageSize)); logger.debug("Comments for case {} are {}", caseId, caseComments); List<CaseComment> comments = ConvertUtils.transformCaseComments(caseComments); CaseCommentList commentsList = new CaseCommentList(comments); return commentsList; } }