--- /dev/null
+/*-\r
+ * ============LICENSE_START=======================================================\r
+ * ONAP - SO\r
+ * ================================================================================\r
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
+ * ================================================================================\r
+ * Modifications Copyright (c) 2019 Samsung\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.oran.otf.camunda.workflow;\r
+\r
+import org.oran.otf.camunda.configuration.OtfCamundaConfiguration;\r
+import org.oran.otf.camunda.exception.TestExecutionException;\r
+import org.oran.otf.camunda.exception.WorkflowProcessorException;\r
+import org.oran.otf.camunda.model.ExecutionConstants.ExecutionVariable;\r
+import org.oran.otf.camunda.model.ExecutionConstants.TestResult;\r
+import org.oran.otf.camunda.model.WorkflowResponse;\r
+import org.oran.otf.camunda.service.ProcessEngineAwareService;\r
+import org.oran.otf.camunda.workflow.utility.WorkflowUtility;\r
+import org.oran.otf.common.model.*;\r
+import org.oran.otf.common.model.historic.TestDefinitionHistoric;\r
+import org.oran.otf.common.model.historic.TestInstanceHistoric;\r
+import org.oran.otf.common.model.local.BpmnInstance;\r
+import org.oran.otf.common.model.local.ParallelFlowInput;\r
+import org.oran.otf.common.repository.*;\r
+import org.oran.otf.common.utility.Utility;\r
+import org.oran.otf.common.utility.database.Generic;\r
+import org.oran.otf.common.utility.permissions.PermissionChecker;\r
+import org.oran.otf.common.utility.permissions.UserPermission;\r
+import com.mongodb.client.result.UpdateResult;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Objects;\r
+import java.util.UUID;\r
+import org.bson.types.ObjectId;\r
+import org.camunda.bpm.BpmPlatform;\r
+import org.camunda.bpm.engine.RepositoryService;\r
+import org.camunda.bpm.engine.RuntimeService;\r
+import org.camunda.bpm.engine.repository.ProcessDefinition;\r
+import org.camunda.bpm.engine.runtime.ProcessInstance;\r
+import org.camunda.bpm.engine.variable.VariableMap;\r
+import org.camunda.bpm.engine.variable.Variables;\r
+import org.camunda.bpm.engine.variable.impl.VariableMapImpl;\r
+import org.oran.otf.common.model.*;\r
+import org.oran.otf.common.repository.*;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.boot.context.event.ApplicationReadyEvent;\r
+import org.springframework.context.event.EventListener;\r
+import org.springframework.data.mongodb.core.MongoTemplate;\r
+import org.springframework.data.mongodb.core.query.Criteria;\r
+import org.springframework.data.mongodb.core.query.Query;\r
+import org.springframework.data.mongodb.core.query.Update;\r
+import org.springframework.stereotype.Component;\r
+\r
+@Component\r
+public class WorkflowProcessor extends ProcessEngineAwareService {\r
+\r
+ private static final String logPrefix = Utility.getLoggerPrefix();\r
+ private static final Logger logger = LoggerFactory.getLogger(WorkflowProcessor.class);\r
+\r
+ @Autowired\r
+ GroupRepository groupRepository;\r
+ @Autowired\r
+ TestDefinitionRepository testDefinitionRepository;\r
+ @Autowired\r
+ TestInstanceRepository testInstanceRepository;\r
+ @Autowired\r
+ UserRepository userRepository;\r
+ @Autowired\r
+ TestExecutionRepository testExecutionRepository;\r
+ @Autowired\r
+ MongoTemplate mongoOperation;\r
+ @Autowired\r
+ WorkflowUtility workflowUtility;\r
+\r
+ private RuntimeService runtimeService;\r
+ private RepositoryService repositoryService;\r
+\r
+ // Note: the business key is used to identify the process in unit tests\r
+ protected static String getBusinessKey(Map<String, Object> inputVariables) {\r
+ return getOrCreate(inputVariables, "otf-business-key");\r
+ }\r
+\r
+ protected static Map<String, Object> getInputVariables(VariableMapImpl variableMap) {\r
+ Map<String, Object> inputVariables = new HashMap<>();\r
+ @SuppressWarnings("unchecked")\r
+ Map<String, Object> vMap = (Map<String, Object>) variableMap.get("variables");\r
+ for (Map.Entry<String, Object> entry : vMap.entrySet()) {\r
+ String vName = entry.getKey();\r
+ Object value = entry.getValue();\r
+ @SuppressWarnings("unchecked")\r
+ Map<String, Object> valueMap = (Map<String, Object>) value; // value, type\r
+ inputVariables.put(vName, valueMap.get("value"));\r
+ }\r
+ return inputVariables;\r
+ }\r
+\r
+ protected static String getOrCreate(Map<String, Object> inputVariables, String key) {\r
+ String value = Objects.toString(inputVariables.get(key), null);\r
+ if (value == null) {\r
+ value = UUID.randomUUID().toString();\r
+ inputVariables.put(key, value);\r
+ }\r
+ return value;\r
+ }\r
+\r
+ private static void buildVariable(\r
+ String key, String value, Map<String, Object> variableValueType) {\r
+ Map<String, Object> host = new HashMap<>();\r
+ host.put("value", value);\r
+ host.put("type", "String");\r
+ variableValueType.put(key, host);\r
+ }\r
+\r
+ @EventListener(ApplicationReadyEvent.class)\r
+ private void initialize() {\r
+ if (this.runtimeService == null) {\r
+ this.runtimeService =\r
+ BpmPlatform.getProcessEngineService()\r
+ .getProcessEngine(OtfCamundaConfiguration.processEngineName)\r
+ .getRuntimeService();\r
+ }\r
+ if (this.repositoryService == null) {\r
+ this.repositoryService =\r
+ BpmPlatform.getProcessEngineService()\r
+ .getProcessEngine(OtfCamundaConfiguration.processEngineName)\r
+ .getRepositoryService();\r
+ }\r
+ }\r
+\r
+ public TestExecution processWorkflowRequest(WorkflowRequest request)\r
+ throws WorkflowProcessorException {\r
+\r
+ // Check if the test instance exists.\r
+ TestInstance testInstance =\r
+ Generic.findByIdGeneric(testInstanceRepository, request.getTestInstanceId());\r
+ if (testInstance == null) {\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String.format(\r
+ "Test instance with identifier %s was not found.",\r
+ request.getTestInstanceId().toString()));\r
+ response.setMessageCode(404);\r
+ response.setResponse("Unable to start the test instance.");\r
+ TestExecution testExecution = generateTestExecution(request, null, null, null);\r
+ testExecution.setTestResult(TestResult.DOES_NOT_EXIST);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+\r
+ // Override the test data and vth input of the instance if the request contains the data.\r
+ Map<String, Object> vthInput =\r
+ request.getVthInput() == null ? testInstance.getVthInput() : request.getVthInput();\r
+ Map<String, Object> testData =\r
+ request.getTestData() == null ? testInstance.getTestData() : request.getTestData();\r
+ Map<String, ParallelFlowInput> plfoInput =\r
+ request.getPfloInput() == null ? testInstance.getPfloInput() : request.getPfloInput();\r
+\r
+ testInstance.setVthInput((HashMap<String, Object>) vthInput);\r
+ testInstance.setTestData((HashMap<String, Object>) testData);\r
+ testInstance.setPfloInput((HashMap<String, ParallelFlowInput>) plfoInput);\r
+\r
+\r
+ // Check if the test definition linked to the test instance is also present.\r
+ TestDefinition testDefinition =\r
+ Generic.findByIdGeneric(testDefinitionRepository, testInstance.getTestDefinitionId());\r
+ if (testDefinition == null) {\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String.format(\r
+ "Test definition with identifier %s was not found.",\r
+ testInstance.getTestDefinitionId().toString()));\r
+ response.setMessageCode(404);\r
+ response.setResponse("Unable to start the test instance.");\r
+ TestExecution testExecution = generateTestExecution(request, testInstance, null, null);\r
+ testExecution.setTestResult(TestResult.DOES_NOT_EXIST);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+\r
+ // is using latest defintion, verify that the processDefinitionId within camunda is present in\r
+ // the test definition bpmn instance list\r
+ if (testInstance.isUseLatestTestDefinition()) {\r
+ String processDefinitionId =\r
+ findLatestProcessDefinition(testDefinition.getProcessDefinitionKey());\r
+ boolean isBpmnInstancePresent =\r
+ verifyIdExistsInTestDefinition(testDefinition, processDefinitionId);\r
+ if (isBpmnInstancePresent) {\r
+ testInstance.setProcessDefinitionId(processDefinitionId);\r
+ } else {\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String.format(\r
+ "Latest Test Definition does not exist for key %s.",\r
+ testDefinition.getProcessDefinitionKey()));\r
+ response.setMessageCode(404);\r
+ response.setResponse("Unable to start the test instance.");\r
+ TestExecution testExecution =\r
+ generateTestExecution(request, testInstance, testDefinition, null);\r
+ testExecution.setTestResult(TestResult.DOES_NOT_EXIST);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+ }\r
+\r
+ // Check if the entity making the request has permission to run the test instance.\r
+ User executor = Generic.findByIdGeneric(userRepository, request.getExecutorId());\r
+ if (executor == null) {\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String\r
+ .format("User with id %s was not found.", request.getExecutorId().toString()));\r
+ response.setMessageCode(404);\r
+ response.setResponse("Unable to start the test instance.");\r
+ TestExecution testExecution =\r
+ generateTestExecution(request, testInstance, testDefinition, null);\r
+ testExecution.setTestResult(TestResult.DOES_NOT_EXIST);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+// if (!workflowUtility.hasPermission(executor, testInstance)) {\r
+// WorkflowResponse response = new WorkflowResponse();\r
+// response.setMessage(\r
+// String.format(\r
+// "The user with email %s does not have permission to execute test instance with id: %s.",\r
+// executor.getEmail(), testInstance.get_id().toString()));\r
+// response.setMessageCode(401);\r
+// response.setResponse("Unauthorized to execute the test instance.");\r
+// TestExecution testExecution =\r
+// generateTestExecution(request, testInstance, testDefinition, executor);\r
+// testExecution.setTestResult(TestResult.UNAUTHORIZED);\r
+// testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+// response.setTestExecution(testExecution);\r
+// throw new WorkflowProcessorException(response);\r
+// }\r
+ Group testInstanceGroup = groupRepository.findById(testInstance.getGroupId().toString()).orElse(null);\r
+ if(testInstanceGroup == null){\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String.format("unable to find test instance group. Group id: %s",testInstance.getGroupId().toString()));\r
+ response.setMessageCode(404);\r
+ response.setResponse("unable to find test instance group");\r
+ TestExecution testExecution = generateTestExecution(request,testInstance,testDefinition,executor);\r
+ testExecution.setTestResult(TestResult.DOES_NOT_EXIST);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+ if (!PermissionChecker.hasPermissionTo(executor,testInstanceGroup, UserPermission.Permission.EXECUTE,groupRepository)){\r
+ WorkflowResponse response = new WorkflowResponse();\r
+ response.setMessage(\r
+ String.format(\r
+ "User with email: %s does not have execute permission on test instance group with id: %s",\r
+ executor.getEmail(),testInstance.getGroupId().toString()));\r
+ response.setMessageCode(401);\r
+ response.setResponse("unauthorized to execute test instance");\r
+ TestExecution testExecution = generateTestExecution(request,testInstance,testDefinition,executor);\r
+ testExecution.setTestResult(TestResult.UNAUTHORIZED);\r
+ testExecution.setTestDetails(generateTestDetailsWithMessage(response.getMessage()));\r
+ response.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(response);\r
+ }\r
+\r
+ // Generate a testExecution with a historic copy of the test instance, test definition, and the\r
+ // email of the person executing the test.\r
+ TestExecution testExecution =\r
+ generateTestExecution(request, testInstance, testDefinition, executor);\r
+\r
+ // Prepare the test details, test result, test execution, and vth input variables for the\r
+ // process instance.\r
+ VariableMap variableMap =\r
+ Variables.createVariables()\r
+ .putValueTyped(\r
+ ExecutionVariable.TEST_DETAILS,\r
+ Variables.objectValue(testExecution.getTestDetails()).create())\r
+ .putValueTyped(\r
+ ExecutionVariable.TEST_RESULT,\r
+ Variables.objectValue(testExecution.getTestResult()).create())\r
+ .putValueTyped(\r
+ ExecutionVariable.TEST_RESULT_MESSAGE,\r
+ Variables.objectValue(testExecution.getTestResultMessage()).create())\r
+ .putValueTyped(ExecutionVariable.VTH_INPUT,\r
+ Variables.objectValue(vthInput).create())\r
+ .putValueTyped(ExecutionVariable.TEST_DATA,\r
+ Variables.objectValue(testData).create())\r
+ .putValue(\r
+ ExecutionVariable.TEST_EXECUTION,\r
+ Variables.objectValue(testExecution)\r
+ .serializationDataFormat(Variables.SerializationDataFormats.JAVA)\r
+ .create())\r
+ .putValue(\r
+ ExecutionVariable.PFLO_INPUT,\r
+ Variables.objectValue(plfoInput)\r
+ .serializationDataFormat(Variables.SerializationDataFormats.JAVA)\r
+ .create());\r
+\r
+ if (testInstance.isUseLatestTestDefinition()) {\r
+ return startProcessByKey(\r
+ testDefinition.getProcessDefinitionKey(), variableMap, testExecution);\r
+ } else {\r
+ return startProcessById(testInstance.getProcessDefinitionId(), variableMap,\r
+ testExecution);\r
+ }\r
+ }\r
+\r
+ public TestExecution startProcessByKey(\r
+ String processKey, Map<String, Object> variableMap, TestExecution testExecution) {\r
+ try {\r
+ logger.info(\r
+ "***OTF startProcessInstanceByKey with processKey: {} and variables: {}",\r
+ processKey,\r
+ variableMap);\r
+\r
+ // Set the start time as close to the runtime service start function.\r
+ testExecution.setStartTime(new Date(System.currentTimeMillis()));\r
+ testExecutionRepository.insert(testExecution);\r
+\r
+ ProcessInstance processInstance =\r
+ runtimeService.startProcessInstanceByKey(\r
+ processKey, testExecution.getBusinessKey(), variableMap);\r
+\r
+ // Update the test execution object with the processInstanceId after the processInstanceId is\r
+ // available.\r
+ testExecution.setProcessInstanceId(processInstance.getProcessInstanceId());\r
+ Query query = new Query();\r
+ query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
+ // Also add businessKey as a criteria because the object won't be found if the business key\r
+ // was somehow modified in the workflow.\r
+ query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey()));\r
+ Update update = new Update();\r
+ update.set("processInstanceId", processInstance.getProcessInstanceId());\r
+ UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class);\r
+ // Check the status of the findAndUpdate database, and appropriately handle the errors.\r
+ if (result.getMatchedCount() == 0) {\r
+ throw new TestExecutionException(\r
+ String.format(\r
+ "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.",\r
+ testExecution.get_id(), testExecution.getBusinessKey()));\r
+ } else if (result.getModifiedCount() == 0) {\r
+ throw new TestExecutionException(\r
+ "Unable to persist the testExecution to the database.");\r
+ }\r
+\r
+ logger.debug(\r
+ logPrefix\r
+ + "Process "\r
+ + processKey\r
+ + ":"\r
+ + processInstance.getProcessInstanceId()\r
+ + " "\r
+ + (processInstance.isEnded() ? "ENDED" : "RUNNING"));\r
+ } catch (Exception e) {\r
+ WorkflowResponse workflowResponse = new WorkflowResponse();\r
+ workflowResponse.setResponse("Error occurred while executing the process: " + e);\r
+ workflowResponse.setProcessInstanceId(testExecution.getProcessInstanceId());\r
+ workflowResponse.setMessageCode(500);\r
+ workflowResponse.setMessage("Failed to execute test instance: " + e.getMessage());\r
+ testExecution.setTestResult(TestResult.FAILED);\r
+ testExecution\r
+ .setTestDetails(generateTestDetailsWithMessage(workflowResponse.getMessage()));\r
+ workflowResponse.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(workflowResponse);\r
+ }\r
+\r
+ return testExecution;\r
+ }\r
+\r
+ private TestExecution startProcessById(\r
+ String processId, Map<String, Object> variableMap, TestExecution testExecution) {\r
+ try {\r
+ logger.debug(\r
+ "***OTF startProcessInstanceById with processId: {} and variables: {}",\r
+ processId,\r
+ variableMap);\r
+\r
+ // Set the start time as close to the runtime service start function.\r
+ testExecution.setStartTime(new Date(System.currentTimeMillis()));\r
+ testExecutionRepository.insert(testExecution);\r
+\r
+ ProcessInstance processInstance =\r
+ runtimeService.startProcessInstanceById(\r
+ processId, testExecution.getBusinessKey(), variableMap);\r
+\r
+ // Update the test execution object with the processInstanceId after the processInstanceId is\r
+ // available.\r
+ testExecution.setProcessInstanceId(processInstance.getProcessInstanceId());\r
+ Query query = new Query();\r
+ query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
+ // Also add businessKey as a criteria because the object won't be found if the business key\r
+ // was somehow modified in the workflow.\r
+ query.addCriteria(Criteria.where("businessKey").is(testExecution.getBusinessKey()));\r
+ Update update = new Update();\r
+ update.set("processInstanceId", processInstance.getProcessInstanceId());\r
+ UpdateResult result = mongoOperation.updateFirst(query, update, TestExecution.class);\r
+ // Check the status of the findAndUpdate database, and appropriately handle the errors.\r
+ if (result.getMatchedCount() == 0) {\r
+ throw new TestExecutionException(\r
+ String.format(\r
+ "Unable to log the test result because a testExecution associated with _id, %s and businessKey %s, was not found.",\r
+ testExecution.get_id(), testExecution.getBusinessKey()));\r
+ } else if (result.getModifiedCount() == 0) {\r
+ throw new TestExecutionException(\r
+ "Unable to persist the testExecution to the database.");\r
+ }\r
+\r
+ logger.debug(\r
+ logPrefix\r
+ + "Process "\r
+ + processInstance.getProcessInstanceId()\r
+ + ":"\r
+ + processInstance.getProcessInstanceId()\r
+ + " "\r
+ + (processInstance.isEnded() ? "ENDED" : "RUNNING"));\r
+ } catch (Exception e) {\r
+ WorkflowResponse workflowResponse = new WorkflowResponse();\r
+ workflowResponse.setResponse("Error occurred while executing the process: " + e);\r
+ workflowResponse.setProcessInstanceId(testExecution.getProcessInstanceId());\r
+ workflowResponse.setMessageCode(500);\r
+ workflowResponse.setMessage("Failed to execute test instance: " + e.getMessage());\r
+ testExecution.setTestResult(TestResult.FAILED);\r
+ testExecution\r
+ .setTestDetails(generateTestDetailsWithMessage(workflowResponse.getMessage()));\r
+ workflowResponse.setTestExecution(testExecution);\r
+ throw new WorkflowProcessorException(workflowResponse);\r
+ }\r
+\r
+ return testExecution;\r
+ }\r
+\r
+ private TestExecution generateTestExecution(\r
+ WorkflowRequest request,\r
+ TestInstance testInstance,\r
+ TestDefinition testDefinition,\r
+ User executor) {\r
+ TestExecution testExecution = new TestExecution();\r
+ testExecution.set_id(new ObjectId());\r
+ testExecution.setExecutorId(request.getExecutorId());\r
+ testExecution.setAsync(request.isAsync());\r
+ testExecution.setStartTime(null);\r
+ testExecution.setTestDetails(new HashMap<>());\r
+ testExecution.setTestResult(TestResult.UNKNOWN);\r
+ testExecution.setTestResultMessage("");\r
+ testExecution.setProcessInstanceId(null);\r
+ testExecution.setBusinessKey(UUID.randomUUID().toString());\r
+ testExecution.setTestHeadResults(new ArrayList<>());\r
+ testExecution.setTestInstanceResults(new ArrayList<>());\r
+ if (testInstance != null) {\r
+ testExecution.setGroupId(testInstance.getGroupId());\r
+ TestInstanceHistoric testInstanceHistoric = new TestInstanceHistoric(testInstance);\r
+ testExecution.setHistoricTestInstance(testInstanceHistoric);\r
+ }\r
+ if (testDefinition != null && testInstance != null) {\r
+ TestDefinitionHistoric testDefinitionHistoric =\r
+ new TestDefinitionHistoric(testDefinition, testInstance.getProcessDefinitionId());\r
+ testExecution.setHistoricTestDefinition(testDefinitionHistoric);\r
+ }\r
+ if (executor != null) {\r
+ testExecution.setHistoricEmail(executor.getEmail());\r
+ }\r
+ return testExecution;\r
+ }\r
+\r
+ private Map<String, Object> generateTestDetailsWithMessage(String message) {\r
+ Map<String, Object> map = new HashMap<>();\r
+ map.put("message", message);\r
+ return map;\r
+ }\r
+\r
+ private String findLatestProcessDefinition(String processDefinitionKey) {\r
+ logger.info("Before find process definition key query.");\r
+ ProcessDefinition definition =\r
+ repositoryService\r
+ .createProcessDefinitionQuery()\r
+ .processDefinitionKey(processDefinitionKey)\r
+ .latestVersion()\r
+ .singleResult();\r
+ logger.info("After find process definition key query.");\r
+ String processDefinitionId = null;\r
+ if (definition != null) {\r
+ processDefinitionId = definition.getId();\r
+ }\r
+ return processDefinitionId;\r
+ }\r
+\r
+ private boolean verifyIdExistsInTestDefinition(\r
+ TestDefinition definition, String processDefinitionId) {\r
+ if (processDefinitionId == null || definition == null) {\r
+ return false;\r
+ }\r
+\r
+ List<BpmnInstance> bpmnInstances = definition.getBpmnInstances();\r
+ BpmnInstance bpmnInstance =\r
+ bpmnInstances.stream()\r
+ .filter(\r
+ _bpmnInstance -> {\r
+ return _bpmnInstance.isDeployed()\r
+ && _bpmnInstance.getProcessDefinitionId() != null\r
+ && _bpmnInstance.getProcessDefinitionId().equals(processDefinitionId);\r
+ })\r
+ .findFirst()\r
+ .orElse(null);\r
+ return bpmnInstance != null;\r
+ }\r
+}\r