aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-CxSvc-csar.csarbin86187 -> 85970 bytes
-rw-r--r--asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-VfZrdm5bpxmc02092017Service-csar.csarbin97867 -> 97110 bytes
-rw-r--r--bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/resource/ResourceRequestBuilder.java81
-rw-r--r--bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/ExecuteBuildingBlockRainyDay.java9
-rw-r--r--bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/ExecuteBuildingBlock.bpmn57
-rw-r--r--bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn42
-rw-r--r--bpmn/so-bpmn-building-blocks/src/test/java/org/onap/so/bpmn/infrastructure/bpmn/subprocess/ExecuteBuildingBlockTest.java8
-rw-r--r--bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateE2EServiceInstance.groovy1
-rw-r--r--bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateResources.groovy281
-rw-r--r--bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowAction.java1
-rw-r--r--bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java95
-rw-r--r--bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasksTest.java72
12 files changed, 412 insertions, 235 deletions
diff --git a/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-CxSvc-csar.csar b/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-CxSvc-csar.csar
index 9add57f1dd..82c249ef27 100644
--- a/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-CxSvc-csar.csar
+++ b/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-CxSvc-csar.csar
Binary files differ
diff --git a/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-VfZrdm5bpxmc02092017Service-csar.csar b/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-VfZrdm5bpxmc02092017Service-csar.csar
index 69b1c23404..4c906aba38 100644
--- a/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-VfZrdm5bpxmc02092017Service-csar.csar
+++ b/asdc-controller/src/test/resources/resource-examples/WorkflowBpmn/service-VfZrdm5bpxmc02092017Service-csar.csar
Binary files differ
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/resource/ResourceRequestBuilder.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/resource/ResourceRequestBuilder.java
index 35bd25fabf..0cce8b3f94 100644
--- a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/resource/ResourceRequestBuilder.java
+++ b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/common/resource/ResourceRequestBuilder.java
@@ -38,6 +38,8 @@ import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory;
import org.onap.sdc.toscaparser.api.NodeTemplate;
import org.onap.sdc.toscaparser.api.Property;
+import org.onap.sdc.toscaparser.api.RequirementAssignment;
+import org.onap.sdc.toscaparser.api.RequirementAssignments;
import org.onap.sdc.toscaparser.api.functions.GetInput;
import org.onap.sdc.toscaparser.api.parameters.Input;
import org.onap.so.bpmn.core.UrnPropertiesReader;
@@ -63,15 +65,88 @@ public class ResourceRequestBuilder {
static JsonUtils jsonUtil = new JsonUtils();
- /**
- * build the resource Parameters detail.
+ public static List<String> getResourceSequence(Execution execution, String serviceUuid) {
+ List<String> resouceSequence = new ArrayList<String>();
+ List<NodeTemplate> resultList = new ArrayList<NodeTemplate>();
+ String csarpath = null;
+ try {
+ csarpath = getCsarFromUuid(serviceUuid);
+
+ SdcToscaParserFactory toscaParser = SdcToscaParserFactory.getInstance();
+ ISdcCsarHelper iSdcCsarHelper = toscaParser.getSdcCsarHelper(csarpath, false);
+ List<NodeTemplate> nodeTemplates = iSdcCsarHelper.getServiceNodeTemplates();
+ List<NodeTemplate> nodes = new ArrayList<NodeTemplate>();
+ nodes.addAll(nodeTemplates);
+
+ for (NodeTemplate nodeTemplate : nodeTemplates) {
+ RequirementAssignments requirement = iSdcCsarHelper.getRequirementsOf(nodeTemplate);
+
+ if (requirement == null || requirement.getAll() == null || requirement.getAll().isEmpty()) {
+ resultList.add(nodeTemplate);
+ nodes.remove(nodeTemplate);
+ }
+ }
+
+ resultList = getRequirementList(resultList, nodes, iSdcCsarHelper);
+
+ for (NodeTemplate node : resultList) {
+ String templateName = node.getMetaData().getValue("name");
+ if (!resouceSequence.contains(templateName)) {
+ resouceSequence.add(templateName);
+ }
+ }
+
+ } catch (SdcToscaParserException toscarParserE) {
+ LOGGER.debug("sdc tosca parser failed for csar: " + csarpath, toscarParserE);
+ return resouceSequence;
+ } catch (Exception e) {
+ LOGGER.debug("csar file is not available for service uuid:" + serviceUuid, e);
+ return resouceSequence;
+ }
+
+ return resouceSequence;
+ }
+
+ private static List<NodeTemplate> getRequirementList(List<NodeTemplate> resultList, List<NodeTemplate> nodeTemplates,
+ ISdcCsarHelper iSdcCsarHelper) {
+
+ List<NodeTemplate> nodes = new ArrayList<NodeTemplate>();
+ nodes.addAll(nodeTemplates);
+
+ for (NodeTemplate nodeTemplate : nodeTemplates) {
+ RequirementAssignments requirement = iSdcCsarHelper.getRequirementsOf(nodeTemplate);
+ List<RequirementAssignment> reqAs = requirement.getAll();
+ for (RequirementAssignment ra : reqAs) {
+ String reqNode = ra.getNodeTemplateName();
+ for (NodeTemplate rNode : resultList) {
+ if (rNode.getName().equals(reqNode)) {
+ if(!resultList.contains(nodeTemplate)) {
+ resultList.add(nodeTemplate);
+ }
+ if(nodes.contains(nodeTemplate)) {
+ nodes.remove(nodeTemplate);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (!nodes.isEmpty()) {
+ getRequirementList(resultList, nodes, iSdcCsarHelper);
+ }
+
+ return resultList;
+ }
+
+ /* build the resource Parameters detail.
* It's a json string for resource instantiant
* {
* "locationConstraints":[...]
* "requestInputs":{K,V}
* }
* <br>
- *
+ *
* @param execution Execution context
* @param serviceUuid The service template uuid
* @param resourceCustomizationUuid The resource customization uuid
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/ExecuteBuildingBlockRainyDay.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/ExecuteBuildingBlockRainyDay.java
index 70d523eab4..d8f9a66568 100644
--- a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/ExecuteBuildingBlockRainyDay.java
+++ b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/ExecuteBuildingBlockRainyDay.java
@@ -39,6 +39,7 @@ import org.springframework.stereotype.Component;
public class ExecuteBuildingBlockRainyDay {
private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, ExecuteBuildingBlockRainyDay.class);
+ public static final String HANDLING_CODE = "handlingCode";
@Autowired
private CatalogDbClient catalogDbClient;
@@ -107,10 +108,14 @@ public class ExecuteBuildingBlockRainyDay {
handlingCode = rainyDayHandlerStatus.getPolicy();
}
msoLogger.debug("RainyDayHandler Status Code is: " + handlingCode);
- execution.setVariable("handlingCode", handlingCode);
+ execution.setVariable(HANDLING_CODE, handlingCode);
} catch (Exception e) {
msoLogger.debug("RainyDayHandler Status Code is: Abort");
- execution.setVariable("handlingCode", "Abort");
+ execution.setVariable(HANDLING_CODE, "Abort");
}
}
+
+ public void setHandlingStatusSuccess(DelegateExecution execution){
+ execution.setVariable(HANDLING_CODE, "Success");
+ }
}
diff --git a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/ExecuteBuildingBlock.bpmn b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/ExecuteBuildingBlock.bpmn
index 01d88b91dc..57a5557391 100644
--- a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/ExecuteBuildingBlock.bpmn
+++ b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/ExecuteBuildingBlock.bpmn
@@ -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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.10.0">
+<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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.8.2">
<bpmn:process id="ExecuteBuildingBlock" name="ExecuteBuildingBlock" isExecutable="true">
<bpmn:startEvent id="Start_ExecuteBuildingBlock" name="start">
<bpmn:outgoing>SequenceFlow_0rq4c5r</bpmn:outgoing>
@@ -20,22 +20,18 @@
<bpmn:outgoing>SequenceFlow_0uzwjrq</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="End_ExecuteBuildingBlock" name="end">
- <bpmn:incoming>SequenceFlow_01h9qmz</bpmn:incoming>
- <bpmn:incoming>SequenceFlow_1ryv9sh</bpmn:incoming>
+ <bpmn:incoming>SequenceFlow_16lmcxp</bpmn:incoming>
</bpmn:endEvent>
- <bpmn:sequenceFlow id="SequenceFlow_01h9qmz" sourceRef="Call_BBToExecute" targetRef="End_ExecuteBuildingBlock" />
+ <bpmn:sequenceFlow id="SequenceFlow_01h9qmz" sourceRef="Call_BBToExecute" targetRef="Task_setHandlingCodeSuccess" />
<bpmn:sequenceFlow id="Continue" name="Continue" sourceRef="CheckOrchestrationStatusValidationResults" targetRef="Call_BBToExecute" />
<bpmn:serviceTask id="StatusPolicy" name="StatusPolicy" camunda:expression="${OrchestrationStatusValidator.validateOrchestrationStatus(InjectExecution.execute(execution, execution.getVariable(&#34;gBuildingBlockExecution&#34;)))}">
<bpmn:incoming>SequenceFlow_0uzwjrq</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0je0y25</bpmn:outgoing>
</bpmn:serviceTask>
- <bpmn:sequenceFlow id="SequenceFlow_1ryv9sh" name="SilentSuccess" sourceRef="CheckOrchestrationStatusValidationResults" targetRef="End_ExecuteBuildingBlock">
- <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("orchestrationStatusValidationResult").name() == "SILENT_SUCCESS"}]]></bpmn:conditionExpression>
- </bpmn:sequenceFlow>
<bpmn:exclusiveGateway id="CheckOrchestrationStatusValidationResults" name="Check OrchestrationStatus Validation Results" default="Continue">
<bpmn:incoming>SequenceFlow_0je0y25</bpmn:incoming>
<bpmn:outgoing>Continue</bpmn:outgoing>
- <bpmn:outgoing>SequenceFlow_1ryv9sh</bpmn:outgoing>
+ <bpmn:outgoing>SequenceFlow_1j0vskt</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="SequenceFlow_0je0y25" sourceRef="StatusPolicy" targetRef="CheckOrchestrationStatusValidationResults" />
<bpmn:subProcess id="SubProcess_0tv8zda" name="Error Handling&#10;&#10;" triggeredByEvent="true">
@@ -91,6 +87,15 @@
<bpmn:terminateEventDefinition />
</bpmn:endEvent>
</bpmn:subProcess>
+ <bpmn:sequenceFlow id="SequenceFlow_16lmcxp" sourceRef="Task_setHandlingCodeSuccess" targetRef="End_ExecuteBuildingBlock" />
+ <bpmn:sequenceFlow id="SequenceFlow_1j0vskt" name="Silent Success" sourceRef="CheckOrchestrationStatusValidationResults" targetRef="Task_setHandlingCodeSuccess">
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("orchestrationStatusValidationResult").name() == "SILENT_SUCCESS"}]]></bpmn:conditionExpression>
+ </bpmn:sequenceFlow>
+ <bpmn:serviceTask id="Task_setHandlingCodeSuccess" name="Set Handling Code To Success" camunda:expression="${ExecuteBuildingBlockRainyDay.setHandlingStatusSuccess(execution)}">
+ <bpmn:incoming>SequenceFlow_01h9qmz</bpmn:incoming>
+ <bpmn:incoming>SequenceFlow_1j0vskt</bpmn:incoming>
+ <bpmn:outgoing>SequenceFlow_16lmcxp</bpmn:outgoing>
+ </bpmn:serviceTask>
</bpmn:process>
<bpmn:error id="Error_0tnktdw" name="Error" errorCode="java.lang.Exception" />
<bpmn:error id="Error_17zcdbk" name="Bpmn Error" />
@@ -123,16 +128,16 @@
<dc:Bounds x="141" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_0ahsxzi_di" bpmnElement="End_ExecuteBuildingBlock">
- <dc:Bounds x="808" y="162" width="36" height="36" />
+ <dc:Bounds x="871" y="162" width="36" height="36" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="817" y="202" width="18" height="12" />
+ <dc:Bounds x="880" y="202" width="18" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_01h9qmz_di" bpmnElement="SequenceFlow_01h9qmz">
<di:waypoint xsi:type="dc:Point" x="689" y="180" />
- <di:waypoint xsi:type="dc:Point" x="808" y="180" />
+ <di:waypoint xsi:type="dc:Point" x="731" y="180" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="703.5" y="159" width="90" height="12" />
+ <dc:Bounds x="665" y="159" width="90" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="ExclusiveGateway_0ey4zpt_di" bpmnElement="ExclusiveGateway_0ey4zpt" isMarkerVisible="true">
@@ -217,15 +222,6 @@
<bpmndi:BPMNShape id="ServiceTask_0brnbqx_di" bpmnElement="StatusPolicy">
<dc:Bounds x="307" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
- <bpmndi:BPMNEdge id="SequenceFlow_1ryv9sh_di" bpmnElement="SequenceFlow_1ryv9sh">
- <di:waypoint xsi:type="dc:Point" x="483" y="155" />
- <di:waypoint xsi:type="dc:Point" x="483" y="75" />
- <di:waypoint xsi:type="dc:Point" x="826" y="75" />
- <di:waypoint xsi:type="dc:Point" x="826" y="162" />
- <bpmndi:BPMNLabel>
- <dc:Bounds x="620" y="54" width="69" height="12" />
- </bpmndi:BPMNLabel>
- </bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="ExclusiveGateway_0f8ghh3_di" bpmnElement="CheckOrchestrationStatusValidationResults" isMarkerVisible="true">
<dc:Bounds x="458" y="155" width="50" height="50" />
<bpmndi:BPMNLabel>
@@ -274,6 +270,25 @@
<dc:Bounds x="763" y="514" width="18" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="SequenceFlow_16lmcxp_di" bpmnElement="SequenceFlow_16lmcxp">
+ <di:waypoint xsi:type="dc:Point" x="831" y="180" />
+ <di:waypoint xsi:type="dc:Point" x="871" y="180" />
+ <bpmndi:BPMNLabel>
+ <dc:Bounds x="851" y="159" width="0" height="12" />
+ </bpmndi:BPMNLabel>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="SequenceFlow_1j0vskt_di" bpmnElement="SequenceFlow_1j0vskt">
+ <di:waypoint xsi:type="dc:Point" x="483" y="155" />
+ <di:waypoint xsi:type="dc:Point" x="483" y="84" />
+ <di:waypoint xsi:type="dc:Point" x="781" y="84" />
+ <di:waypoint xsi:type="dc:Point" x="781" y="140" />
+ <bpmndi:BPMNLabel>
+ <dc:Bounds x="597" y="63" width="72" height="12" />
+ </bpmndi:BPMNLabel>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNShape id="ServiceTask_0z9izx5_di" bpmnElement="Task_setHandlingCodeSuccess">
+ <dc:Bounds x="731" y="140" width="100" height="80" />
+ </bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
diff --git a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn
index 13dad149cd..8cda1d7c7b 100644
--- a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn
+++ b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WorkflowActionBB.bpmn
@@ -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.10.0">
+<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:process id="WorkflowActionBB" name="WorkflowActionBB" isExecutable="true">
<bpmn:startEvent id="Start_WorkflowActionBB" name="start">
<bpmn:outgoing>SequenceFlow_15s0okp</bpmn:outgoing>
@@ -39,7 +39,7 @@
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="SequenceFlow_07h9d4y" sourceRef="Call_ExecuteBB" targetRef="ExclusiveGateway_Finished" />
<bpmn:sequenceFlow id="SequenceFlow_1m2eezj" name="Completed = true" sourceRef="ExclusiveGateway_Finished" targetRef="ExclusiveGateway_isTopLevelFlowC">
- <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("completed")==true&&execution.getVariable("handlingCode")=="Success"}]]></bpmn:conditionExpression>
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("completed")==true&&execution.getVariable("isRollback")==false}]]></bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:serviceTask id="Task_RetrieveBBExectuionList" name="Retrieve BB Execution List" camunda:expression="${WorkflowAction.selectExecutionList(execution)}">
<bpmn:incoming>SequenceFlow_15s0okp</bpmn:incoming>
@@ -148,10 +148,9 @@
</bpmn:sequenceFlow>
<bpmn:exclusiveGateway id="ExclusiveGateway_isTopLevelFlowC" name="Is Top-Level Flow?" default="SequenceFlow_0kf5sen">
<bpmn:incoming>SequenceFlow_1m2eezj</bpmn:incoming>
- <bpmn:outgoing>SequenceFlow_0kf5sen</bpmn:outgoing>
<bpmn:outgoing>SequenceFlow_0x4urgp</bpmn:outgoing>
+ <bpmn:outgoing>SequenceFlow_0kf5sen</bpmn:outgoing>
</bpmn:exclusiveGateway>
- <bpmn:sequenceFlow id="SequenceFlow_0kf5sen" name="yes" sourceRef="ExclusiveGateway_isTopLevelFlowC" targetRef="Task_SetupCompleteMsoProcess" />
<bpmn:sequenceFlow id="SequenceFlow_0x4urgp" name="no" sourceRef="ExclusiveGateway_isTopLevelFlowC" targetRef="End_WorkflowActionBB">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("isTopLevelFlow")==false}]]></bpmn:conditionExpression>
</bpmn:sequenceFlow>
@@ -161,13 +160,13 @@
<bpmn:sequenceFlow id="SequenceFlow_11dlyzt" name="Rollback Not Needed" sourceRef="Task_RollbackExecutionPath" targetRef="Task_UpdateRequestToFailed">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("isRollbackNeeded")==false}]]></bpmn:conditionExpression>
</bpmn:sequenceFlow>
- <bpmn:serviceTask id="Task_UpdateRequestToFailed" name="Update Request To Failed" camunda:expression="${WorkflowActionBBTasks.updateRequestStatusToFailed(execution)}">
+ <bpmn:serviceTask id="Task_UpdateRequestToFailed" name="Update Request To Failed" camunda:expression="${WorkflowActionBBTasks.updateRequestStatusToFailedWithRollback(execution)}">
<bpmn:incoming>SequenceFlow_11dlyzt</bpmn:incoming>
<bpmn:incoming>SequenceFlow_0l7kaba</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1ui67mc</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:sequenceFlow id="SequenceFlow_0l7kaba" name="Rollback Completed" sourceRef="ExclusiveGateway_Finished" targetRef="Task_UpdateRequestToFailed">
- <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("completed")==true&&execution.getVariable("handlingCode")=="PreformingRollback"}]]></bpmn:conditionExpression>
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${execution.getVariable("completed")==true&&execution.getVariable("isRollback")==true}]]></bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="SequenceFlow_1ui67mc" sourceRef="Task_UpdateRequestToFailed" targetRef="End_RollbackFailed" />
<bpmn:subProcess id="SubProcess_0fuugr9" name="Java Exception Handling Sub Process" triggeredByEvent="true">
@@ -190,6 +189,7 @@
<bpmn:outgoing>SequenceFlow_0mew9im</bpmn:outgoing>
</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_SetupCompleteMsoProcess" />
</bpmn:process>
<bpmn:error id="Error_0kd2o2a" name="java.lang.Exception" errorCode="java.lang.Exception" />
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
@@ -203,7 +203,7 @@
<bpmndi:BPMNShape id="EndEvent_1uv6erv_di" bpmnElement="End_WorkflowActionBB">
<dc:Bounds x="1281" y="147" width="36" height="36" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="1290" y="186" width="19" height="13" />
+ <dc:Bounds x="1291" y="186" width="18" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_15s0okp_di" bpmnElement="SequenceFlow_15s0okp">
@@ -263,7 +263,7 @@
<di:waypoint xsi:type="dc:Point" x="1000" y="250" />
<di:waypoint xsi:type="dc:Point" x="1027" y="250" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="1014" y="229" width="0" height="0" />
+ <dc:Bounds x="969" y="229" width="90" height="0" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1rscv7d_di" bpmnElement="SequenceFlow_1rscv7d">
@@ -272,7 +272,7 @@
<di:waypoint xsi:type="dc:Point" x="1147" y="165" />
<di:waypoint xsi:type="dc:Point" x="1281" y="165" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="1117" y="207.5" width="90" height="0" />
+ <dc:Bounds x="1117" y="208" width="90" height="0" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="SubProcess_18226x4_di" bpmnElement="SubProcess_18226x4" isExpanded="true">
@@ -394,7 +394,7 @@
<bpmndi:BPMNShape id="ExclusiveGateway_001g41v_di" bpmnElement="ExclusiveGateway_isTopLevelFlowAbort" isMarkerVisible="true">
<dc:Bounds x="841" y="20" width="50" height="50" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="835" y="70" width="61" height="24" />
+ <dc:Bounds x="836" y="70" width="60" height="24" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_02ksbt0_di" bpmnElement="SequenceFlow_02ksbt0">
@@ -415,22 +415,14 @@
<bpmndi:BPMNShape id="ExclusiveGateway_1er1kam_di" bpmnElement="ExclusiveGateway_isTopLevelFlowC" isMarkerVisible="true">
<dc:Bounds x="841" y="140" width="50" height="50" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="835" y="108" width="61" height="24" />
+ <dc:Bounds x="836" y="108" width="60" height="24" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
- <bpmndi:BPMNEdge id="SequenceFlow_0kf5sen_di" bpmnElement="SequenceFlow_0kf5sen">
- <di:waypoint xsi:type="dc:Point" x="866" y="190" />
- <di:waypoint xsi:type="dc:Point" x="866" y="250" />
- <di:waypoint xsi:type="dc:Point" x="900" y="250" />
- <bpmndi:BPMNLabel>
- <dc:Bounds x="872" y="220" width="18" height="12" />
- </bpmndi:BPMNLabel>
- </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_0x4urgp_di" bpmnElement="SequenceFlow_0x4urgp">
<di:waypoint xsi:type="dc:Point" x="891" y="165" />
<di:waypoint xsi:type="dc:Point" x="1281" y="165" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="1080.2065217391305" y="140" width="13" height="13" />
+ <dc:Bounds x="1081" y="140" width="12" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="EndEvent_1q8eh5e_di" bpmnElement="End_RollbackFailed">
@@ -482,7 +474,7 @@
<di:waypoint xsi:type="dc:Point" x="915" y="365" />
<di:waypoint xsi:type="dc:Point" x="940" y="365" />
<bpmndi:BPMNLabel>
- <dc:Bounds x="885" y="358.5" width="90" height="13" />
+ <dc:Bounds x="885" y="359" width="90" height="13" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="ExclusiveGateway_10q79b6_di" bpmnElement="ExclusiveGateway_10q79b6" isMarkerVisible="true">
@@ -560,6 +552,14 @@
<dc:Bounds x="530" y="99" width="0" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="SequenceFlow_0kf5sen_di" bpmnElement="SequenceFlow_0kf5sen">
+ <di:waypoint xsi:type="dc:Point" x="866" y="190" />
+ <di:waypoint xsi:type="dc:Point" x="866" y="250" />
+ <di:waypoint xsi:type="dc:Point" x="900" y="250" />
+ <bpmndi:BPMNLabel>
+ <dc:Bounds x="872" y="220" width="18" height="12" />
+ </bpmndi:BPMNLabel>
+ </bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
diff --git a/bpmn/so-bpmn-building-blocks/src/test/java/org/onap/so/bpmn/infrastructure/bpmn/subprocess/ExecuteBuildingBlockTest.java b/bpmn/so-bpmn-building-blocks/src/test/java/org/onap/so/bpmn/infrastructure/bpmn/subprocess/ExecuteBuildingBlockTest.java
index 51f5f723ad..63ded7ee30 100644
--- a/bpmn/so-bpmn-building-blocks/src/test/java/org/onap/so/bpmn/infrastructure/bpmn/subprocess/ExecuteBuildingBlockTest.java
+++ b/bpmn/so-bpmn-building-blocks/src/test/java/org/onap/so/bpmn/infrastructure/bpmn/subprocess/ExecuteBuildingBlockTest.java
@@ -59,7 +59,7 @@ public class ExecuteBuildingBlockTest extends BaseBPMNTest {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("ExecuteBuildingBlock", variables);
assertThat(pi).isNotNull();
assertThat(pi).isStarted()
- .hasPassedInOrder("Start_ExecuteBuildingBlock", "Task_BBInputSetup", "StatusPolicy", "CheckOrchestrationStatusValidationResults", "End_ExecuteBuildingBlock")
+ .hasPassedInOrder("Start_ExecuteBuildingBlock", "Task_BBInputSetup", "StatusPolicy", "CheckOrchestrationStatusValidationResults","Task_setHandlingCodeSuccess", "End_ExecuteBuildingBlock")
.hasNotPassed("Call_BBToExecute", "ErrorStart", "Task_QueryRainyDayTable", "ExclusiveGateway_1aonzik", "ExclusiveGateway_1aonzik", "ErrorEnd2", "Task_SetRetryTimer");
assertThat(pi).isEnded();
}
@@ -71,7 +71,7 @@ public class ExecuteBuildingBlockTest extends BaseBPMNTest {
assertThat(pi).isNotNull();
assertThat(pi).isStarted()
.hasPassedInOrder("Start_ExecuteBuildingBlock", "Task_BBInputSetup", "BoundaryEvent_0i3q236", "Task_QueryRainyDayTable", "ExclusiveGateway_1aonzik", "ErrorEnd2")
- .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Call_BBToExecute", "End_ExecuteBuildingBlock", "ExclusiveGateway_0ey4zpt", "Task_SetRetryTimer");
+ .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Task_setHandlingCodeSuccess","Call_BBToExecute", "End_ExecuteBuildingBlock", "ExclusiveGateway_0ey4zpt", "Task_SetRetryTimer");
assertThat(pi).isEnded();
}
@@ -86,7 +86,7 @@ public class ExecuteBuildingBlockTest extends BaseBPMNTest {
assertThat(pi).isNotNull();
assertThat(pi).isStarted()
.hasPassedInOrder("Start_ExecuteBuildingBlock", "Task_BBInputSetup", "BoundaryEvent_0i3q236", "Task_QueryRainyDayTable", "ExclusiveGateway_1aonzik", "ExclusiveGateway_0ey4zpt", "ErrorEnd2")
- .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Call_BBToExecute", "End_ExecuteBuildingBlock", "Task_SetRetryTimer");
+ .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Task_setHandlingCodeSuccess","Call_BBToExecute", "End_ExecuteBuildingBlock", "Task_SetRetryTimer");
assertThat(pi).isEnded();
}
@@ -108,6 +108,6 @@ public class ExecuteBuildingBlockTest extends BaseBPMNTest {
managementService.executeJob(job.getId());
assertThat(pi).isEnded()
.hasPassedInOrder("Start_ExecuteBuildingBlock", "Task_BBInputSetup", "BoundaryEvent_0i3q236", "Task_QueryRainyDayTable", "ExclusiveGateway_1aonzik", "ExclusiveGateway_0ey4zpt", "Task_SetRetryTimer", "EndEvent_1sez2lh")
- .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Call_BBToExecute", "End_ExecuteBuildingBlock", "ErrorEnd2");
+ .hasNotPassed("StatusPolicy", "CheckOrchestrationStatusValidationResults", "Task_setHandlingCodeSuccess","Call_BBToExecute", "End_ExecuteBuildingBlock", "ErrorEnd2");
}
}
diff --git a/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateE2EServiceInstance.groovy b/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateE2EServiceInstance.groovy
index 4b848024d6..de998a5f9c 100644
--- a/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateE2EServiceInstance.groovy
+++ b/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateE2EServiceInstance.groovy
@@ -165,6 +165,7 @@ public class DoCreateE2EServiceInstance extends AbstractServiceTaskProcessor {
${statusLine}
<model-invariant-id>${MsoUtils.xmlEscape(modelInvariantUuid)}</model-invariant-id>
<model-version-id>${MsoUtils.xmlEscape(modelUuid)}</model-version-id>
+ <input-parameters>${MsoUtils.xmlEscape(uuiRequest)}</input-parameters>
</service-instance>""".trim()
execution.setVariable("serviceInstanceData", serviceInstanceData)
msoLogger.debug(serviceInstanceData)
diff --git a/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateResources.groovy b/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateResources.groovy
index 482da23b33..2167025e18 100644
--- a/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateResources.groovy
+++ b/bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateResources.groovy
@@ -17,7 +17,7 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-
+
package org.onap.so.bpmn.infrastructure.scripts
import org.onap.so.bpmn.infrastructure.properties.BPMNProperties
@@ -69,41 +69,37 @@ import org.onap.so.logger.MsoLogger
*
* Outputs:
* @param - WorkflowException
-
*/
public class DoCreateResources extends AbstractServiceTaskProcessor{
- private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, DoCreateResources.class);
+ private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, DoCreateResources.class);
+
+ ExceptionUtil exceptionUtil = new ExceptionUtil()
+ JsonUtils jsonUtil = new JsonUtils()
+ CatalogDbUtils cutils = new CatalogDbUtils()
- ExceptionUtil exceptionUtil = new ExceptionUtil()
- JsonUtils jsonUtil = new JsonUtils()
- CatalogDbUtils cutils = new CatalogDbUtils()
+ public void preProcessRequest(DelegateExecution execution) {
+ msoLogger.trace("preProcessRequest ")
+ String msg = ""
- public void preProcessRequest(DelegateExecution execution)
- {
- msoLogger.trace("preProcessRequest ")
- String msg = ""
-
List addResourceList = execution.getVariable("addResourceList")
- if (addResourceList == null)
- {
+ if (addResourceList == null) {
msg = "Input addResourceList is null"
msoLogger.info(msg)
- exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
+ exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
}
- else if (addResourceList.size() == 0)
- {
+ else if (addResourceList.size() == 0) {
msg = "No resource in addResourceList"
msoLogger.info(msg)
}
msoLogger.trace("Exit preProcessRequest ")
}
-
- public void sequenceResoure(DelegateExecution execution)
- {
+
+ public void sequenceResoure(DelegateExecution execution) {
msoLogger.trace("Start sequenceResoure Process ")
- String serviceModelUUID = execution.getVariable("modelUuid")
-
+ String incomingRequest = execution.getVariable("uuiRequest")
+ String serviceModelUuid = jsonUtil.getJsonValue(incomingRequest,"service.serviceUuid")
+
List<Resource> addResourceList = execution.getVariable("addResourceList")
List<NetworkResource> networkResourceList = new ArrayList<NetworkResource>()
@@ -112,40 +108,47 @@ public class DoCreateResources extends AbstractServiceTaskProcessor{
String serviceDecompose = execution.getVariable("serviceDecomposition")
String serviceModelName = jsonUtil.getJsonValue(serviceDecompose, "serviceResources.modelInfo.modelName")
+
+ // get Sequence from properties
def resourceSequence = BPMNProperties.getResourceSequenceProp(serviceModelName)
+ // get Sequence from csar(model)
+ if(resourceSequence == null) {
+ resourceSequence = ResourceRequestBuilder.getResourceSequence(execution, serviceModelUuid)
+ msoLogger.info("Get Sequence from csar : " + resourceSequence)
+ }
+
if(resourceSequence != null) {
- // sequence is defined in config file
- for (resourceType in resourceSequence) {
- for (resource in addResourceList) {
- if (StringUtils.containsIgnoreCase(resource.getModelInfo().getModelName(), resourceType)) {
- sequencedResourceList.add(resource)
-
- if (resource instanceof NetworkResource) {
- networkResourceList.add(resource)
+ for (resourceType in resourceSequence) {
+ for (resource in addResourceList) {
+ if (StringUtils.containsIgnoreCase(resource.getModelInfo().getModelName(), resourceType)) {
+ sequencedResourceList.add(resource)
+
+ if (resource instanceof NetworkResource) {
+ networkResourceList.add(resource)
+ }
}
}
}
- }
} else {
-
- //define sequenced resource list, we deploy vf first and then network and then ar
- //this is defaule sequence
- List<VnfResource> vnfResourceList = new ArrayList<VnfResource>()
- List<AllottedResource> arResourceList = new ArrayList<AllottedResource>()
-
- for (Resource rc : addResourceList){
- if (rc instanceof VnfResource) {
- vnfResourceList.add(rc)
- } else if (rc instanceof NetworkResource) {
- networkResourceList.add(rc)
- } else if (rc instanceof AllottedResource) {
- arResourceList.add(rc)
+
+ //define sequenced resource list, we deploy vf first and then network and then ar
+ //this is defaule sequence
+ List<VnfResource> vnfResourceList = new ArrayList<VnfResource>()
+ List<AllottedResource> arResourceList = new ArrayList<AllottedResource>()
+
+ for (Resource rc : addResourceList){
+ if (rc instanceof VnfResource) {
+ vnfResourceList.add(rc)
+ } else if (rc instanceof NetworkResource) {
+ networkResourceList.add(rc)
+ } else if (rc instanceof AllottedResource) {
+ arResourceList.add(rc)
+ }
}
- }
- sequencedResourceList.addAll(vnfResourceList)
- sequencedResourceList.addAll(networkResourceList)
- sequencedResourceList.addAll(arResourceList)
+ sequencedResourceList.addAll(vnfResourceList)
+ sequencedResourceList.addAll(networkResourceList)
+ sequencedResourceList.addAll(arResourceList)
}
String isContainsWanResource = networkResourceList.isEmpty() ? "false" : "true"
@@ -154,11 +157,11 @@ public class DoCreateResources extends AbstractServiceTaskProcessor{
String serviceNeedSDNC = "mso.workflow.custom." + serviceModelName + ".sdnc.need";
isContainsWanResource = BPMNProperties.getProperty(serviceNeedSDNC, isContainsWanResource)
}
-
+
execution.setVariable("isContainsWanResource", isContainsWanResource)
execution.setVariable("currentResourceIndex", 0)
execution.setVariable("sequencedResourceList", sequencedResourceList)
- msoLogger.info("sequencedResourceList: " + sequencedResourceList)
+ msoLogger.info("sequencedResourceList: " + sequencedResourceList)
msoLogger.trace("COMPLETED sequenceResoure Process ")
}
@@ -181,105 +184,105 @@ public class DoCreateResources extends AbstractServiceTaskProcessor{
msoLogger.trace("======== End prepareServiceTopologyRequest Process ======== ")
}
-
+
public void getCurrentResoure(DelegateExecution execution){
- msoLogger.trace("Start getCurrentResoure Process ")
- def currentIndex = execution.getVariable("currentResourceIndex")
- List<Resource> sequencedResourceList = execution.getVariable("sequencedResourceList")
- Resource currentResource = sequencedResourceList.get(currentIndex)
- execution.setVariable("resourceType", currentResource.getModelInfo().getModelName())
- msoLogger.info("Now we deal with resouce:" + currentResource.getModelInfo().getModelName())
- msoLogger.trace("COMPLETED getCurrentResoure Process ")
+ msoLogger.trace("Start getCurrentResoure Process ")
+ def currentIndex = execution.getVariable("currentResourceIndex")
+ List<Resource> sequencedResourceList = execution.getVariable("sequencedResourceList")
+ Resource currentResource = sequencedResourceList.get(currentIndex)
+ execution.setVariable("resourceType", currentResource.getModelInfo().getModelName())
+ msoLogger.info("Now we deal with resouce:" + currentResource.getModelInfo().getModelName())
+ msoLogger.trace("COMPLETED getCurrentResoure Process ")
}
-
+
public void parseNextResource(DelegateExecution execution){
- msoLogger.trace("Start parseNextResource Process ")
+ msoLogger.trace("Start parseNextResource Process ")
def currentIndex = execution.getVariable("currentResourceIndex")
def nextIndex = currentIndex + 1
execution.setVariable("currentResourceIndex", nextIndex)
- List<String> sequencedResourceList = execution.getVariable("sequencedResourceList")
+ List<String> sequencedResourceList = execution.getVariable("sequencedResourceList")
if(nextIndex >= sequencedResourceList.size()){
execution.setVariable("allResourceFinished", "true")
}else{
execution.setVariable("allResourceFinished", "false")
}
- msoLogger.trace("COMPLETED parseNextResource Process ")
- }
-
- public void prepareResourceRecipeRequest(DelegateExecution execution){
- msoLogger.trace("Start prepareResourceRecipeRequest Process ")
- ResourceInput resourceInput = new ResourceInput()
- String serviceInstanceName = execution.getVariable("serviceInstanceName")
- String resourceType = execution.getVariable("resourceType")
- String resourceInstanceName = resourceType + "_" + serviceInstanceName
- resourceInput.setResourceInstanceName(resourceInstanceName)
- msoLogger.info("Prepare Resource Request resourceInstanceName:" + resourceInstanceName)
- String globalSubscriberId = execution.getVariable("globalSubscriberId")
- String serviceType = execution.getVariable("serviceType")
- String serviceInstanceId = execution.getVariable("serviceInstanceId")
- String operationId = execution.getVariable("operationId")
- String operationType = "createInstance"
- resourceInput.setGlobalSubscriberId(globalSubscriberId)
- resourceInput.setServiceType(serviceType)
- resourceInput.setServiceInstanceId(serviceInstanceId)
- resourceInput.setOperationId(operationId)
- resourceInput.setOperationType(operationType);
- def currentIndex = execution.getVariable("currentResourceIndex")
- List<Resource> sequencedResourceList = execution.getVariable("sequencedResourceList")
- Resource currentResource = sequencedResourceList.get(currentIndex)
- resourceInput.setResourceModelInfo(currentResource.getModelInfo());
- ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
- resourceInput.setServiceModelInfo(serviceDecomposition.getModelInfo());
- def String resourceCustomizationUuid = currentResource.getModelInfo().getModelCustomizationUuid();
-
- String incomingRequest = execution.getVariable("uuiRequest")
- //set the requestInputs from tempalte To Be Done
- String serviceModelUuid = jsonUtil.getJsonValue(incomingRequest,"service.serviceUuid")
- String serviceParameters = jsonUtil.getJsonValue(incomingRequest, "service.parameters")
- String resourceParameters = ResourceRequestBuilder.buildResourceRequestParameters(execution, serviceModelUuid, resourceCustomizationUuid, serviceParameters)
- resourceInput.setResourceParameters(resourceParameters)
- resourceInput.setRequestsInputs(incomingRequest)
- execution.setVariable("resourceInput", resourceInput)
- msoLogger.trace("COMPLETED prepareResourceRecipeRequest Process ")
- }
-
- public void executeResourceRecipe(DelegateExecution execution){
- msoLogger.trace("Start executeResourceRecipe Process ")
-
- try {
- String requestId = execution.getVariable("msoRequestId")
- String serviceInstanceId = execution.getVariable("serviceInstanceId")
- String serviceType = execution.getVariable("serviceType")
- ResourceInput resourceInput = execution.getVariable("resourceInput")
-
- // requestAction is action, not opertiontype
- //String requestAction = resourceInput.getOperationType()
- String requestAction = "createInstance"
- JSONObject resourceRecipe = cutils.getResourceRecipe(execution, resourceInput.getResourceModelInfo().getModelUuid(), requestAction)
-
- if (resourceRecipe != null) {
- String recipeURL = BPMNProperties.getProperty("bpelURL", "http://mso:8080") + resourceRecipe.getString("orchestrationUri")
- int recipeTimeOut = resourceRecipe.getInt("recipeTimeout")
- String recipeParamXsd = resourceRecipe.get("paramXSD")
- HttpResponse resp = BpmnRestClient.post(recipeURL, requestId, recipeTimeOut, requestAction, serviceInstanceId, serviceType, resourceInput.toString(), recipeParamXsd)
- } else {
- String exceptionMessage = "Resource receipe is not found for resource modeluuid: " +
- resourceInput.getResourceModelInfo().getModelUuid()
- msoLogger.trace(exceptionMessage)
- exceptionUtil.buildAndThrowWorkflowException(execution, 500, exceptionMessage)
- }
-
- msoLogger.trace("======== end executeResourceRecipe Process ======== ")
- }catch(BpmnError b){
- msoLogger.debug("Rethrowing MSOWorkflowException")
- throw b
- }catch(Exception e){
- msoLogger.debug("Error occured within DoCreateResources executeResourceRecipe method: " + e)
- exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured during DoCreateResources executeResourceRecipe Catalog")
- }
- }
-
- public void postConfigRequest(DelegateExecution execution){
- //now do noting
- }
+ msoLogger.trace("COMPLETED parseNextResource Process ")
+ }
+
+ public void prepareResourceRecipeRequest(DelegateExecution execution){
+ msoLogger.trace("Start prepareResourceRecipeRequest Process ")
+ ResourceInput resourceInput = new ResourceInput()
+ String serviceInstanceName = execution.getVariable("serviceInstanceName")
+ String resourceType = execution.getVariable("resourceType")
+ String resourceInstanceName = resourceType + "_" + serviceInstanceName
+ resourceInput.setResourceInstanceName(resourceInstanceName)
+ msoLogger.info("Prepare Resource Request resourceInstanceName:" + resourceInstanceName)
+ String globalSubscriberId = execution.getVariable("globalSubscriberId")
+ String serviceType = execution.getVariable("serviceType")
+ String serviceInstanceId = execution.getVariable("serviceInstanceId")
+ String operationId = execution.getVariable("operationId")
+ String operationType = "createInstance"
+ resourceInput.setGlobalSubscriberId(globalSubscriberId)
+ resourceInput.setServiceType(serviceType)
+ resourceInput.setServiceInstanceId(serviceInstanceId)
+ resourceInput.setOperationId(operationId)
+ resourceInput.setOperationType(operationType);
+ def currentIndex = execution.getVariable("currentResourceIndex")
+ List<Resource> sequencedResourceList = execution.getVariable("sequencedResourceList")
+ Resource currentResource = sequencedResourceList.get(currentIndex)
+ resourceInput.setResourceModelInfo(currentResource.getModelInfo());
+ ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
+ resourceInput.setServiceModelInfo(serviceDecomposition.getModelInfo());
+ def String resourceCustomizationUuid = currentResource.getModelInfo().getModelCustomizationUuid();
+
+ String incomingRequest = execution.getVariable("uuiRequest")
+ //set the requestInputs from tempalte To Be Done
+ String serviceModelUuid = jsonUtil.getJsonValue(incomingRequest,"service.serviceUuid")
+ String serviceParameters = jsonUtil.getJsonValue(incomingRequest, "service.parameters")
+ String resourceParameters = ResourceRequestBuilder.buildResourceRequestParameters(execution, serviceModelUuid, resourceCustomizationUuid, serviceParameters)
+ resourceInput.setResourceParameters(resourceParameters)
+ resourceInput.setRequestsInputs(incomingRequest)
+ execution.setVariable("resourceInput", resourceInput)
+ msoLogger.trace("COMPLETED prepareResourceRecipeRequest Process ")
+ }
+
+ public void executeResourceRecipe(DelegateExecution execution){
+ msoLogger.trace("Start executeResourceRecipe Process ")
+
+ try {
+ String requestId = execution.getVariable("msoRequestId")
+ String serviceInstanceId = execution.getVariable("serviceInstanceId")
+ String serviceType = execution.getVariable("serviceType")
+ ResourceInput resourceInput = execution.getVariable("resourceInput")
+
+ // requestAction is action, not opertiontype
+ //String requestAction = resourceInput.getOperationType()
+ String requestAction = "createInstance"
+ JSONObject resourceRecipe = cutils.getResourceRecipe(execution, resourceInput.getResourceModelInfo().getModelUuid(), requestAction)
+
+ if (resourceRecipe != null) {
+ String recipeURL = BPMNProperties.getProperty("bpelURL", "http://mso:8080") + resourceRecipe.getString("orchestrationUri")
+ int recipeTimeOut = resourceRecipe.getInt("recipeTimeout")
+ String recipeParamXsd = resourceRecipe.get("paramXSD")
+ HttpResponse resp = BpmnRestClient.post(recipeURL, requestId, recipeTimeOut, requestAction, serviceInstanceId, serviceType, resourceInput.toString(), recipeParamXsd)
+ } else {
+ String exceptionMessage = "Resource receipe is not found for resource modeluuid: " +
+ resourceInput.getResourceModelInfo().getModelUuid()
+ msoLogger.trace(exceptionMessage)
+ exceptionUtil.buildAndThrowWorkflowException(execution, 500, exceptionMessage)
+ }
+
+ msoLogger.trace("======== end executeResourceRecipe Process ======== ")
+ }catch(BpmnError b){
+ msoLogger.debug("Rethrowing MSOWorkflowException")
+ throw b
+ }catch(Exception e){
+ msoLogger.debug("Error occured within DoCreateResources executeResourceRecipe method: " + e)
+ exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured during DoCreateResources executeResourceRecipe Catalog")
+ }
+ }
+
+ public void postConfigRequest(DelegateExecution execution){
+ //now do noting
+ }
}
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowAction.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowAction.java
index 2d5638c2b7..e7d09f83e0 100644
--- a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowAction.java
+++ b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowAction.java
@@ -290,6 +290,7 @@ public class WorkflowAction {
execution.setVariable(G_CURRENT_SEQUENCE, 0);
execution.setVariable("retryCount", 0);
+ execution.setVariable("isRollback", false);
execution.setVariable("flowsToExecute", flowsToExecute);
} catch (Exception ex) {
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java
index d3f817c2a5..8a16b54bf4 100644
--- a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java
+++ b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasks.java
@@ -50,6 +50,7 @@ public class WorkflowActionBBTasks {
private static final String G_REQUEST_ID = "mso-request-id";
private static final String G_ALACARTE = "aLaCarte";
private static final String G_ACTION = "requestAction";
+ private static final String RETRY_COUNT = "retryCount";
private static final Logger logger = LoggerFactory.getLogger(WorkflowActionBBTasks.class);
@Autowired
@@ -221,13 +222,18 @@ public class WorkflowActionBBTasks {
}
public void checkRetryStatus(DelegateExecution execution) {
- if (execution.getVariable("handlingCode").equals("Retry")) {
- int currSequence = (int) execution.getVariable("gCurrentSequence");
- currSequence--;
- execution.setVariable("gCurrentSequence", currSequence);
- int currRetryCount = (int) execution.getVariable("retryCount");
- currRetryCount++;
- execution.setVariable("retryCount", currRetryCount);
+ String handlingCode = (String) execution.getVariable("handlingCode");
+ int retryCount = (int) execution.getVariable(RETRY_COUNT);
+ if (handlingCode.equals("Retry")){
+ if(retryCount<5){
+ int currSequence = (int) execution.getVariable("gCurrentSequence");
+ execution.setVariable("gCurrentSequence", currSequence-1);
+ execution.setVariable(RETRY_COUNT, retryCount + 1);
+ }else{
+ workflowAction.buildAndThrowException(execution, "Exceeded maximum retries. Ending flow with status Abort");
+ }
+ }else{
+ execution.setVariable(RETRY_COUNT, 0);
}
}
@@ -236,37 +242,41 @@ public class WorkflowActionBBTasks {
* layer will rollback the flow its currently working on.
*/
public void rollbackExecutionPath(DelegateExecution execution) {
- List<ExecuteBuildingBlock> flowsToExecute = (List<ExecuteBuildingBlock>) execution
- .getVariable("flowsToExecute");
- List<ExecuteBuildingBlock> rollbackFlows = new ArrayList();
- int currentSequence = (int) execution.getVariable(G_CURRENT_SEQUENCE) + 1;
- int listSize = flowsToExecute.size();
- for (int i = listSize - 1; i >= 0; i--) {
- if (i >= currentSequence) {
- flowsToExecute.remove(i);
- } else {
- ExecuteBuildingBlock ebb = flowsToExecute.get(i);
- BuildingBlock bb = flowsToExecute.get(i).getBuildingBlock();
- String flowName = flowsToExecute.get(i).getBuildingBlock().getBpmnFlowName();
- if (flowName.contains("Assign")) {
- flowName = "Unassign" + flowName.substring(6, flowName.length());
- } else if (flowName.contains("Create")) {
- flowName = "Delete" + flowName.substring(6, flowName.length());
- } else if (flowName.contains("Activate")) {
- flowName = "Deactivate" + flowName.substring(8, flowName.length());
- }else{
- continue;
+ if(!(boolean)execution.getVariable("isRollback")){
+ List<ExecuteBuildingBlock> flowsToExecute = (List<ExecuteBuildingBlock>) execution
+ .getVariable("flowsToExecute");
+ List<ExecuteBuildingBlock> rollbackFlows = new ArrayList();
+ int currentSequence = (int) execution.getVariable(G_CURRENT_SEQUENCE);
+ int listSize = flowsToExecute.size();
+ for (int i = listSize - 1; i >= 0; i--) {
+ if (i > currentSequence - 1) {
+ flowsToExecute.remove(i);
+ } else {
+ String flowName = flowsToExecute.get(i).getBuildingBlock().getBpmnFlowName();
+ if (flowName.contains("Assign")) {
+ flowName = "Unassign" + flowName.substring(6, flowName.length());
+ } else if (flowName.contains("Create")) {
+ flowName = "Delete" + flowName.substring(6, flowName.length());
+ } else if (flowName.contains("Activate")) {
+ flowName = "Deactivate" + flowName.substring(8, flowName.length());
+ }else{
+ continue;
+ }
+ flowsToExecute.get(i).getBuildingBlock().setBpmnFlowName(flowName);
+ rollbackFlows.add(flowsToExecute.get(i));
}
- flowsToExecute.get(i).getBuildingBlock().setBpmnFlowName(flowName);
- rollbackFlows.add(flowsToExecute.get(i));
}
+ if (rollbackFlows.isEmpty())
+ execution.setVariable("isRollbackNeeded", false);
+ else
+ execution.setVariable("isRollbackNeeded", true);
+ execution.setVariable("flowsToExecute", rollbackFlows);
+ execution.setVariable("handlingCode", "PreformingRollback");
+ execution.setVariable("isRollback", true);
+ execution.setVariable("gCurrentSequence", 0);
+ }else{
+ workflowAction.buildAndThrowException(execution, "Rollback has already been called. Cannot rollback a request that is currently in the rollback state.");
}
- if (rollbackFlows.isEmpty())
- execution.setVariable("isRollbackNeeded", false);
- else
- execution.setVariable("isRollbackNeeded", true);
- execution.setVariable("flowsToExecute", rollbackFlows);
- execution.setVariable("handlingCode", "PreformingRollback");
}
public void abortCallErrorHandling(DelegateExecution execution) {
@@ -280,9 +290,17 @@ public class WorkflowActionBBTasks {
String requestId = (String) execution.getVariable(G_REQUEST_ID);
InfraActiveRequests request = requestDbclient.getInfraActiveRequestbyRequestId(requestId);
String errorMsg = null;
+ boolean rollback = false;
try {
WorkflowException exception = (WorkflowException) execution.getVariable("WorkflowException");
- request.setStatusMessage(exception.getErrorMessage());
+ if(exception.getErrorMessage()!=null || !exception.getErrorMessage().equals("")){
+ errorMsg = exception.getErrorMessage();
+ rollback = (boolean) execution.getVariable("isRollbackComplete");
+ if(rollback){
+ errorMsg = errorMsg + " + Rollback has been completed successfully.";
+ }
+ request.setStatusMessage(errorMsg);
+ }
} catch (Exception ex) {
//log error and attempt to extact WorkflowExceptionMessage
logger.error("Failed to extract workflow exception from execution.",ex);
@@ -303,4 +321,9 @@ public class WorkflowActionBBTasks {
workflowAction.buildAndThrowException(execution, "Error Updating Request Database", e);
}
}
+
+ public void updateRequestStatusToFailedWithRollback(DelegateExecution execution) {
+ execution.setVariable("isRollbackComplete", true);
+ updateRequestStatusToFailed(execution);
+ }
}
diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasksTest.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasksTest.java
index 6cac238482..8ed1f44b8a 100644
--- a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasksTest.java
+++ b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/workflow/tasks/WorkflowActionBBTasksTest.java
@@ -23,17 +23,22 @@ package org.onap.so.bpmn.infrastructure.workflow.tasks;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
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.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
import org.onap.so.bpmn.BaseTaskTest;
import org.onap.so.bpmn.servicedecomposition.entities.BuildingBlock;
import org.onap.so.bpmn.servicedecomposition.entities.ExecuteBuildingBlock;
@@ -150,59 +155,99 @@ public class WorkflowActionBBTasksTest extends BaseTaskTest {
@Test
public void rollbackExecutionPathTest(){
+ execution.setVariable("isRollback", false);
List<ExecuteBuildingBlock> flowsToExecute = new ArrayList();
ExecuteBuildingBlock ebb1 = new ExecuteBuildingBlock();
BuildingBlock bb1 = new BuildingBlock();
bb1.setBpmnFlowName("AssignVfModuleBB");
- flowsToExecute.add(ebb1);
ebb1.setBuildingBlock(bb1);
+ flowsToExecute.add(ebb1);
ExecuteBuildingBlock ebb2 = new ExecuteBuildingBlock();
BuildingBlock bb2 = new BuildingBlock();
bb2.setBpmnFlowName("CreateVfModuleBB");
- flowsToExecute.add(ebb2);
ebb2.setBuildingBlock(bb2);
+ flowsToExecute.add(ebb2);
ExecuteBuildingBlock ebb3 = new ExecuteBuildingBlock();
BuildingBlock bb3 = new BuildingBlock();
bb3.setBpmnFlowName("ActivateVfModuleBB");
- flowsToExecute.add(ebb3);
ebb3.setBuildingBlock(bb3);
+ flowsToExecute.add(ebb3);
execution.setVariable("flowsToExecute", flowsToExecute);
- execution.setVariable("gCurrentSequence", 2);
+ execution.setVariable("gCurrentSequence", 3);
workflowActionBBTasks.rollbackExecutionPath(execution);
List<ExecuteBuildingBlock> ebbs = (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute");
assertEquals(ebbs.get(0).getBuildingBlock().getBpmnFlowName(),"DeactivateVfModuleBB");
assertEquals(ebbs.get(1).getBuildingBlock().getBpmnFlowName(),"DeleteVfModuleBB");
- assertEquals(ebbs.get(2).getBuildingBlock().getBpmnFlowName(),"UnassignVfModuleBB");
+ assertEquals(ebbs.get(2).getBuildingBlock().getBpmnFlowName(),"UnassignVfModuleBB");
+ assertEquals(0,execution.getVariable("gCurrentSequence"));
}
@Test
public void rollbackExecutionPathUnfinishedFlowTest(){
+ execution.setVariable("isRollback", false);
List<ExecuteBuildingBlock> flowsToExecute = new ArrayList();
ExecuteBuildingBlock ebb1 = new ExecuteBuildingBlock();
BuildingBlock bb1 = new BuildingBlock();
bb1.setBpmnFlowName("AssignVfModuleBB");
- flowsToExecute.add(ebb1);
ebb1.setBuildingBlock(bb1);
+ flowsToExecute.add(ebb1);
ExecuteBuildingBlock ebb2 = new ExecuteBuildingBlock();
BuildingBlock bb2 = new BuildingBlock();
bb2.setBpmnFlowName("CreateVfModuleBB");
- flowsToExecute.add(ebb2);
ebb2.setBuildingBlock(bb2);
+ flowsToExecute.add(ebb2);
ExecuteBuildingBlock ebb3 = new ExecuteBuildingBlock();
BuildingBlock bb3 = new BuildingBlock();
bb3.setBpmnFlowName("ActivateVfModuleBB");
- flowsToExecute.add(ebb3);
ebb3.setBuildingBlock(bb3);
+ flowsToExecute.add(ebb3);
execution.setVariable("flowsToExecute", flowsToExecute);
- execution.setVariable("gCurrentSequence", 1);
+ execution.setVariable("gCurrentSequence", 2);
workflowActionBBTasks.rollbackExecutionPath(execution);
List<ExecuteBuildingBlock> ebbs = (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute");
assertEquals(ebbs.get(0).getBuildingBlock().getBpmnFlowName(),"DeleteVfModuleBB");
assertEquals(ebbs.get(1).getBuildingBlock().getBpmnFlowName(),"UnassignVfModuleBB");
+ assertEquals(0,execution.getVariable("gCurrentSequence"));
+ }
+
+ @Test
+ public void rollbackExecutionTest(){
+ execution.setVariable("isRollback", false);
+ List<ExecuteBuildingBlock> flowsToExecute = new ArrayList();
+ ExecuteBuildingBlock ebb1 = new ExecuteBuildingBlock();
+ BuildingBlock bb1 = new BuildingBlock();
+ bb1.setBpmnFlowName("AssignServiceInstanceBB");
+ ebb1.setBuildingBlock(bb1);
+ flowsToExecute.add(ebb1);
+ ExecuteBuildingBlock ebb2 = new ExecuteBuildingBlock();
+ BuildingBlock bb2 = new BuildingBlock();
+ bb2.setBpmnFlowName("CreateNetworkCollectionBB");
+ ebb2.setBuildingBlock(bb2);
+ flowsToExecute.add(ebb2);
+ ExecuteBuildingBlock ebb3 = new ExecuteBuildingBlock();
+ BuildingBlock bb3 = new BuildingBlock();
+ bb3.setBpmnFlowName("AssignNetworkBB");
+ ebb3.setBuildingBlock(bb3);
+ flowsToExecute.add(ebb3);
+ ExecuteBuildingBlock ebb4 = new ExecuteBuildingBlock();
+ BuildingBlock bb4 = new BuildingBlock();
+ bb4.setBpmnFlowName("CreateNetworkBB");
+ ebb4.setBuildingBlock(bb4);
+ flowsToExecute.add(ebb4);
+
+ execution.setVariable("flowsToExecute", flowsToExecute);
+ execution.setVariable("gCurrentSequence", 3);
+
+ workflowActionBBTasks.rollbackExecutionPath(execution);
+ List<ExecuteBuildingBlock> ebbs = (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute");
+ assertEquals(ebbs.get(0).getBuildingBlock().getBpmnFlowName(),"UnassignNetworkBB");
+ assertEquals(ebbs.get(1).getBuildingBlock().getBpmnFlowName(),"DeleteNetworkCollectionBB");
+ assertEquals(ebbs.get(2).getBuildingBlock().getBpmnFlowName(),"UnassignServiceInstanceBB");
+ assertEquals(0,execution.getVariable("gCurrentSequence"));
}
@Test
@@ -213,4 +258,13 @@ public class WorkflowActionBBTasksTest extends BaseTaskTest {
workflowActionBBTasks.checkRetryStatus(execution);
assertEquals(0,execution.getVariable("gCurrentSequence"));
}
+
+ @Test
+ public void checkRetryStatusNoRetryTest(){
+ execution.setVariable("retryCount", 3);
+ execution.setVariable("handlingCode","Success");
+ execution.setVariable("gCurrentSequence",1);
+ workflowActionBBTasks.checkRetryStatus(execution);
+ assertEquals(0,execution.getVariable("retryCount"));
+ }
}