validation for vnfs before WorkflowAction starts 11/75711/1
authorBenjamin, Max (mb388a) <mb388a@us.att.com>
Sat, 12 Jan 2019 02:09:59 +0000 (21:09 -0500)
committerBenjamin, Max (mb388a) <mb388a@us.att.com>
Sat, 12 Jan 2019 02:10:13 +0000 (21:10 -0500)
Removed accidental merge markup from WorkflowActionBB
Addition of prevalidation to WorkflowActionBB.
Implement more JUnits for validation methods.
Implement verification of deleteInstance workflow for VNR configuration
dependencies.
Added a validation mechanism on a workflow level to check for valid
actions.

Change-Id: Icb2859c3b8ece534d4e9831ca5f48a15dfaef58d
Issue-ID: SO-1379
Signed-off-by: Benjamin, Max (mb388a) <mb388a@us.att.com>
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PostWorkflowValidator.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PreWorkflowValidator.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidator.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunner.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorOne.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorTwo.java [new file with mode: 0644]
bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunnerTest.java [new file with mode: 0644]
bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn

diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PostWorkflowValidator.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PostWorkflowValidator.java
new file mode 100644 (file)
index 0000000..46b3c57
--- /dev/null
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+public interface PostWorkflowValidator extends WorkflowValidator {
+
+}
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PreWorkflowValidator.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/PreWorkflowValidator.java
new file mode 100644 (file)
index 0000000..4dad1ea
--- /dev/null
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+public interface PreWorkflowValidator extends WorkflowValidator {
+
+}
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidator.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidator.java
new file mode 100644 (file)
index 0000000..348f913
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+import java.util.Set;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+
+public interface WorkflowValidator {
+
+       
+       /**
+        * Name of the workflow action to be validated
+        * @return
+        */
+       public Set<String> forWorkflowAction();
+       
+       /**
+        * Determines whether or not the workflow should be executed
+        * 
+        * @param execution
+        * @return
+        */
+       public boolean validate(DelegateExecution execution);
+       
+}
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunner.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunner.java
new file mode 100644 (file)
index 0000000..44fbc6d
--- /dev/null
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Priority;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.javatuples.Pair;
+import org.onap.so.client.exception.ExceptionBuilder;
+import org.reflections.Reflections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * Controls running all pre and post validation for workflows.
+ * 
+ * To define a validation you must make it a spring bean and implement either {@link org.onap.so.bpmn.common.validation.PreWorkflowValidator} or 
+ * {@link org.onap.so.bpmn.common.validation.PostWorkflowValidator} your validation will automatically be
+ * run by this class.
+ *
+ */
+@Component
+public class WorkflowValidatorRunner {
+
+       private static Logger logger = LoggerFactory.getLogger(WorkflowValidatorRunner.class);
+       @Autowired
+       private ApplicationContext context;
+       
+       @Autowired
+       private ExceptionBuilder exceptionBuilder;
+       
+       private List<PreWorkflowValidator> preWorkflowValidators;
+       private List<PostWorkflowValidator> postWorkflowValidators;
+
+       
+       @PostConstruct
+       protected void init() {
+               
+               preWorkflowValidators = new ArrayList<>(
+                               Optional.ofNullable(context.getBeansOfType(PreWorkflowValidator.class)).orElse(new HashMap<>()).values());
+               postWorkflowValidators = new ArrayList<>(
+                               Optional.ofNullable(context.getBeansOfType(PostWorkflowValidator.class)).orElse(new HashMap<>()).values());
+       }
+       
+       public boolean preValidate(String workflow, DelegateExecution execution) {
+               return validate(preWorkflowValidators, workflow, execution);
+       }
+       
+       
+       public boolean postValidate(String workflow, DelegateExecution execution) {
+               return validate(postWorkflowValidators, workflow, execution);
+       }
+       
+       
+       protected boolean validate(List<? extends WorkflowValidator> validators, String workflow, DelegateExecution execution) {
+               List<Pair<String, Boolean>> results = runValidations(validators, workflow, execution);
+               
+               if (!results.isEmpty()) {
+                       exceptionBuilder.buildAndThrowWorkflowException(execution, 7000,
+                                       "Failed Validations:\n" + results.stream().map(item -> item.getValue0()).collect(Collectors.joining("\n")));
+               }
+               
+               return true;
+               
+       }
+       protected List<Pair<String, Boolean>> runValidations(List<? extends WorkflowValidator> validators, String workflow, DelegateExecution execution) {
+               
+               List<WorkflowValidator> filtered = filterValidators(validators, workflow);
+               
+               List<Pair<String,Boolean>> results = new ArrayList<>();
+               filtered.forEach(item -> results.add(new Pair<>(item.getClass().getName(), item.validate(execution))));
+               
+               return results.stream().filter(item -> item.getValue1().equals(false)).collect(Collectors.toList());
+       }
+       
+       protected List<WorkflowValidator> filterValidators(List<? extends WorkflowValidator> validators, String workflow) {
+               return validators.stream()
+                               .filter(item -> {
+                                       return item.forWorkflowAction().contains(workflow);
+                               })
+                               .sorted(Comparator.comparing(item -> {
+                                       Priority p = Optional.ofNullable(item.getClass().getAnnotation(Priority.class)).orElse(new Priority() {
+                                               public int value() {
+                                                       return 1000;
+                                               }
+
+                                               @Override
+                                               public Class<? extends Annotation> annotationType() {
+                                                       return Priority.class;
+                                               }
+                                       });
+                                       return p.value();
+                               })).collect(Collectors.toList());
+       }
+       
+       protected <T> List<T> buildalidatorList(Reflections reflections, Class<T> clazz) {
+               List<T> result = new ArrayList<>();
+               try {
+                       for (Class<? extends T> klass : reflections.getSubTypesOf(clazz)) {
+                               result.add(klass.newInstance());
+                       }
+               } catch (InstantiationException | IllegalAccessException e) {
+                       logger.error("failed to build validator list for " + clazz.getName(), e);
+                       throw new RuntimeException(e);
+               }
+               
+               return result;
+       }
+       
+       protected List<PreWorkflowValidator> getPreWorkflowValidators() {
+               return this.preWorkflowValidators;
+       }
+       
+       protected List<PostWorkflowValidator> getPostWorkflowValidators() {
+               return this.postWorkflowValidators;
+       }
+       
+}
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorOne.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorOne.java
new file mode 100644 (file)
index 0000000..9ad87b5
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+@Component
+public class WorkflowPreValidatorOne implements PreWorkflowValidator {
+
+       @Override
+       public Set<String> forWorkflowAction() {
+               
+               return Collections.singleton("test");
+       }
+
+       @Override
+       public boolean validate(DelegateExecution exeuction) {
+               return false;
+       }
+
+}
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorTwo.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowPreValidatorTwo.java
new file mode 100644 (file)
index 0000000..2157c67
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.annotation.Priority;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+@Priority(1)
+@Component
+public class WorkflowPreValidatorTwo implements PreWorkflowValidator {
+
+       @Override
+       public Set<String> forWorkflowAction() {
+               return Collections.singleton("test");
+       }
+
+       @Override
+       public boolean validate(DelegateExecution execution) {
+               return false;
+       }
+
+}
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunnerTest.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/common/validation/WorkflowValidatorRunnerTest.java
new file mode 100644 (file)
index 0000000..313fe6b
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.bpmn.common.validation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.camunda.bpm.engine.delegate.BpmnError;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.camunda.bpm.extension.mockito.delegate.DelegateExecutionFake;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.onap.so.bpmn.common.BuildingBlockExecution;
+import org.onap.so.bpmn.common.DelegateExecutionImpl;
+import org.onap.so.bpmn.core.WorkflowException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {ValidationConfig.class})
+public class WorkflowValidatorRunnerTest {
+
+       @Rule
+    public ExpectedException thrown= ExpectedException.none();
+       
+       @Autowired
+       private WorkflowValidatorRunner runner;
+       
+       @Test
+       public void filterValidatorTest() {
+               
+               WorkflowPreValidatorOne one = new WorkflowPreValidatorOne();
+               WorkflowPreValidatorTwo two = new WorkflowPreValidatorTwo();            
+               List<WorkflowValidator> validators = Arrays.asList(one, two);
+
+               List<WorkflowValidator> result = runner.filterValidators(validators, "test");
+
+               List<WorkflowValidator> expected = Arrays.asList(two, one);
+               
+               assertEquals(expected, result);
+       }
+       
+       @Test
+       public void testValidate() {
+               
+               DelegateExecution execution = new DelegateExecutionFake();
+               execution.setVariable("testProcessKey", "1234");
+               try {
+                       runner.preValidate("test", execution);
+                       fail("exception not thrown");
+               } catch (BpmnError e) {
+                       WorkflowException workflowException = (WorkflowException) execution.getVariable("WorkflowException");
+                       assertEquals("Failed Validations:\norg.onap.so.bpmn.common.validation.WorkflowPreValidatorTwo\norg.onap.so.bpmn.common.validation.WorkflowPreValidatorOne", workflowException.getErrorMessage());
+               }
+               runner.preValidate("test2", mock(DelegateExecution.class));
+       }
+       
+       @Test
+       public void testEmptyList() {
+               boolean result = runner.preValidate("test3", mock(DelegateExecution.class));
+               
+               assertTrue(result);
+       }
+}
index bbb2a8a..38a1ccd 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.8.2">
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.4.0">
   <bpmn:process id="WorkflowActionBB" name="WorkflowActionBB" isExecutable="true">
     <bpmn:startEvent id="Start_WorkflowActionBB" name="start">
       <bpmn:outgoing>SequenceFlow_15s0okp</bpmn:outgoing>
@@ -29,9 +29,8 @@
     <bpmn:sequenceFlow id="SequenceFlow_0mqrkxv" sourceRef="Task_SelectBB" targetRef="ServiceTask_0e2p0xs" />
     <bpmn:serviceTask id="Task_SelectBB" name="Select BB" camunda:expression="${WorkflowActionBBTasks.selectBB(execution)}">
       <bpmn:incoming>SequenceFlow_1atzsgn</bpmn:incoming>
-      <bpmn:incoming>SequenceFlow_1wb59ic</bpmn:incoming>
       <bpmn:incoming>SequenceFlow_005hi8o</bpmn:incoming>
-      <bpmn:incoming>SequenceFlow_0unbew4</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_1tfizxf</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_0mqrkxv</bpmn:outgoing>
     </bpmn:serviceTask>
     <bpmn:exclusiveGateway id="ExclusiveGateway_Finished" default="SequenceFlow_01j184u">
       <bpmn:incoming>SequenceFlow_1r570x3</bpmn:incoming>
     </bpmn:endEvent>
     <bpmn:sequenceFlow id="SequenceFlow_1p8yxu6" sourceRef="Task_AbortAndCallErrorHandling" targetRef="EndEvent_0lzz1ya" />
-    <bpmn:sequenceFlow id="SequenceFlow_1wb59ic" sourceRef="Task_SendSync" targetRef="Task_SelectBB" />
+    <bpmn:sequenceFlow id="SequenceFlow_1wb59ic" sourceRef="Task_SendSync" targetRef="Task_PreValidateWorkflow" />
     <bpmn:sequenceFlow id="SequenceFlow_01j184u" sourceRef="ExclusiveGateway_Finished" targetRef="Task_0a31dkf" />
     <bpmn:sequenceFlow id="SequenceFlow_005hi8o" sourceRef="Task_0a31dkf" targetRef="Task_SelectBB" />
     <bpmn:serviceTask id="Task_0a31dkf" name="Check Retry Status" camunda:expression="${WorkflowActionBBTasks.checkRetryStatus(execution)}">
       <bpmn:outgoing>SequenceFlow_0unbew4</bpmn:outgoing>
     </bpmn:exclusiveGateway>
     <bpmn:sequenceFlow id="SequenceFlow_0sckerv" name="yes" sourceRef="ExclusiveGateway_isTopLevelFlow" targetRef="Task_SendSync" />
-    <bpmn:sequenceFlow id="SequenceFlow_0unbew4" name="no" sourceRef="ExclusiveGateway_isTopLevelFlow" targetRef="Task_SelectBB">
+    <bpmn:sequenceFlow id="SequenceFlow_0unbew4" name="no" sourceRef="ExclusiveGateway_isTopLevelFlow" targetRef="Task_PreValidateWorkflow">
       <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("isTopLevelFlow")==false}]]></bpmn:conditionExpression>
     </bpmn:sequenceFlow>
     <bpmn:exclusiveGateway id="ExclusiveGateway_isTopLevelFlowAbort" name="Is Top-Level Flow?" default="SequenceFlow_02ksbt0">
     </bpmn:serviceTask>
     <bpmn:sequenceFlow id="SequenceFlow_0mew9im" sourceRef="ServiceTask_0e2p0xs" targetRef="Call_ExecuteBB" />
     <bpmn:sequenceFlow id="SequenceFlow_0kf5sen" name="yes" sourceRef="ExclusiveGateway_isTopLevelFlowC" targetRef="Task_UpdateRequestComplete" />
+    <bpmn:sequenceFlow id="SequenceFlow_1tfizxf" sourceRef="Task_PreValidateWorkflow" targetRef="Task_SelectBB" />
+    <bpmn:serviceTask id="Task_PreValidateWorkflow" name="PreValidate Workflow" camunda:expression="${WorkflowValidatorRunner.preValidate(execution.getVariable(&#34;requestAction&#34;), execution)}">
+      <bpmn:incoming>SequenceFlow_0unbew4</bpmn:incoming>
+      <bpmn:incoming>SequenceFlow_1wb59ic</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_1tfizxf</bpmn:outgoing>
+    </bpmn:serviceTask>
   </bpmn:process>
   <bpmn:error id="Error_0kd2o2a" name="java.lang.Exception" errorCode="java.lang.Exception" />
   <bpmndi:BPMNDiagram id="BPMNDiagram_1">
     <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="WorkflowActionBB">
       <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="Start_WorkflowActionBB">
-        <dc:Bounds x="-241" y="102" width="36" height="36" />
+        <dc:Bounds x="-434" y="102" width="36" height="36" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="-234" y="138" width="23" height="12" />
+          <dc:Bounds x="-426" y="138" width="22" height="12" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="EndEvent_1uv6erv_di" bpmnElement="End_WorkflowActionBB">
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_15s0okp_di" bpmnElement="SequenceFlow_15s0okp">
-        <di:waypoint xsi:type="dc:Point" x="-205" y="120" />
-        <di:waypoint xsi:type="dc:Point" x="-172" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-398" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-365" y="120" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="-233" y="99" width="90" height="13" />
+          <dc:Bounds x="-381" y="99" width="0" height="0" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="CallActivity_03m7z4y_di" bpmnElement="Call_ExecuteBB">
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="ServiceTask_0kn8jt8_di" bpmnElement="Task_RetrieveBBExectuionList">
-        <dc:Bounds x="-172" y="80" width="100" height="80" />
+        <dc:Bounds x="-365" y="80" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="ServiceTask_0654g3m_di" bpmnElement="Task_SendSync">
-        <dc:Bounds x="46" y="-7" width="100" height="80" />
+        <dc:Bounds x="-132" y="-6" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="ServiceTask_0wzh11j_di" bpmnElement="Task_UpdateRequestComplete">
         <dc:Bounds x="942" y="206" width="100" height="80" />
         <dc:Bounds x="239" y="222" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_0vc9go9_di" bpmnElement="SequenceFlow_0vc9go9">
-        <di:waypoint xsi:type="dc:Point" x="-72" y="120" />
-        <di:waypoint xsi:type="dc:Point" x="-39" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-265" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-228" y="120" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="-100" y="105" width="90" height="0" />
+          <dc:Bounds x="-246" y="105" width="0" height="0" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_11530ei_di" bpmnElement="SequenceFlow_11530ei">
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_1wb59ic_di" bpmnElement="SequenceFlow_1wb59ic">
-        <di:waypoint xsi:type="dc:Point" x="146" y="33" />
-        <di:waypoint xsi:type="dc:Point" x="193" y="33" />
-        <di:waypoint xsi:type="dc:Point" x="193" y="120" />
-        <di:waypoint xsi:type="dc:Point" x="239" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-32" y="34" />
+        <di:waypoint xsi:type="dc:Point" x="32" y="34" />
+        <di:waypoint xsi:type="dc:Point" x="32" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="80" y="120" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="163" y="77" width="90" height="0" />
+          <dc:Bounds x="47" y="77" width="0" height="0" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_01j184u_di" bpmnElement="SequenceFlow_01j184u">
         <dc:Bounds x="667" y="-76" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="ExclusiveGateway_0ptb1yi_di" bpmnElement="ExclusiveGateway_isTopLevelFlow" isMarkerVisible="true">
-        <dc:Bounds x="-39" y="95" width="50" height="50" />
+        <dc:Bounds x="-228" y="95" width="50" height="50" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="-45" y="145" width="61" height="24" />
+          <dc:Bounds x="-235" y="145" width="63" height="24" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_0sckerv_di" bpmnElement="SequenceFlow_0sckerv">
-        <di:waypoint xsi:type="dc:Point" x="-13" y="96" />
-        <di:waypoint xsi:type="dc:Point" x="-13" y="33" />
-        <di:waypoint xsi:type="dc:Point" x="46" y="33" />
+        <di:waypoint xsi:type="dc:Point" x="-202" y="96" />
+        <di:waypoint xsi:type="dc:Point" x="-202" y="34" />
+        <di:waypoint xsi:type="dc:Point" x="-132" y="34" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="-7" y="55" width="19" height="12" />
+          <dc:Bounds x="-195" y="55.55555555555556" width="18" height="12" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_0unbew4_di" bpmnElement="SequenceFlow_0unbew4">
-        <di:waypoint xsi:type="dc:Point" x="11" y="120" />
-        <di:waypoint xsi:type="dc:Point" x="239" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="-178" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="80" y="120" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="119" y="95" width="12" height="12" />
+          <dc:Bounds x="-87" y="99.95468180757382" width="12" height="12" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="ExclusiveGateway_001g41v_di" bpmnElement="ExclusiveGateway_isTopLevelFlowAbort" isMarkerVisible="true">
           <dc:Bounds x="872" y="217.6" width="18" height="12" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1tfizxf_di" bpmnElement="SequenceFlow_1tfizxf">
+        <di:waypoint xsi:type="dc:Point" x="180" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="211" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="211" y="120" />
+        <di:waypoint xsi:type="dc:Point" x="239" y="120" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="226" y="120" width="0" height="0" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="ServiceTask_0m5xr0e_di" bpmnElement="Task_PreValidateWorkflow">
+        <dc:Bounds x="80" y="80" width="100" height="80" />
+      </bpmndi:BPMNShape>
     </bpmndi:BPMNPlane>
   </bpmndi:BPMNDiagram>
 </bpmn:definitions>