Bug fixes for modify TN NSSI operation 26/118726/1
authorhyu2010 <hyu2010b@gmail.com>
Tue, 2 Mar 2021 19:27:12 +0000 (14:27 -0500)
committerhyu2010 <hyu2010b@gmail.com>
Tue, 2 Mar 2021 19:27:12 +0000 (14:27 -0500)
Modify/re-use of an existing TN NSSI contains problems since
Guilin release. We have planned to resolve these issues in
Honolulu release. This submission contains these fixes.

Issue-ID: SO-3563
Signed-off-by: hyu2010 <hyu2010b@gmail.com>
Change-Id: If2b22260797135eab3cc74c66e0b9a9ec8d91d65

bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoCreateTnNssiInstance.groovy
bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/DoModifyTnNssi.groovy
bpmn/so-bpmn-infrastructure-common/src/main/groovy/org/onap/so/bpmn/infrastructure/scripts/TnNssmfUtils.groovy
bpmn/so-bpmn-infrastructure-flows/src/main/resources/subprocess/DoModifyTransportNSSI.bpmn

index c06e313..78c6a08 100644 (file)
@@ -40,7 +40,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank
 class DoCreateTnNssiInstance extends AbstractServiceTaskProcessor {
 
     private static final Logger logger = LoggerFactory.getLogger(DoCreateTnNssiInstance.class);
-    final String AAI_VERSION = "v21"
     JsonUtils jsonUtil = new JsonUtils()
     TnNssmfUtils tnNssmfUtils = new TnNssmfUtils()
     ExceptionUtil exceptionUtil = new ExceptionUtil()
@@ -226,7 +225,7 @@ class DoCreateTnNssiInstance extends AbstractServiceTaskProcessor {
             if (bwStr != null && !bwStr.isEmpty()) {
                 networkPolicy.setMaxBandwidth(Integer.parseInt(bwStr))
             } else {
-                log.debug("ERROR: createNetworkPolicy: maxBandwidth is null")
+                logger.debug("ERROR: createNetworkPolicy: maxBandwidth is null")
             }
 
             //networkPolicy.setReliability(new Object())
@@ -264,7 +263,9 @@ class DoCreateTnNssiInstance extends AbstractServiceTaskProcessor {
             String networkPolicyId = UUID.randomUUID().toString()
             createNetworkPolicy(execution, ssInstanceId, networkPolicyId)
 
-            tnNssmfUtils.attachNetworkPolicyToAllottedResource(execution, AAI_VERSION, allottedResourceUri, networkPolicyId);
+            tnNssmfUtils.attachNetworkPolicyToAllottedResource(execution, tnNssmfUtils.AAI_VERSION,
+                    allottedResourceUri,
+                    networkPolicyId);
 
         } catch (BpmnError e) {
             throw e
@@ -295,11 +296,11 @@ class DoCreateTnNssiInstance extends AbstractServiceTaskProcessor {
             List<String> linkStrList = jsonUtil.StringArrayToList(linkArrayStr)
 
             for (String linkStr : linkStrList) {
-                String linkName = jsonUtil.getJsonValue(linkStr, "name")
-                if (isBlank(linkName)) {
-                    linkName = "tn-nssmf-" + UUID.randomUUID().toString()
+                String linkId = jsonUtil.getJsonValue(linkStr, "id")
+                if (isBlank(linkId)) {
+                    linkId = "tn-nssmf-" + UUID.randomUUID().toString()
                 }
-                logger.debug("createLogicalLinksForAllocatedResource: linkName=" + linkName)
+                logger.debug("createLogicalLinksForAllocatedResource: linkId=" + linkId)
 
                 String epA = jsonUtil.getJsonValue(linkStr, "transportEndpointA")
                 String epB = jsonUtil.getJsonValue(linkStr, "transportEndpointB")
@@ -307,18 +308,19 @@ class DoCreateTnNssiInstance extends AbstractServiceTaskProcessor {
                 String modelVersionId = execution.getVariable("modelUuid")
 
                 org.onap.aai.domain.yang.LogicalLink resource = new org.onap.aai.domain.yang.LogicalLink()
-                resource.setLinkName(linkName)
-                resource.setLinkId(epA)
+                resource.setLinkId(linkId)
+                resource.setLinkName(epA)
                 resource.setLinkName2(epB)
                 resource.setLinkType("TsciConnectionLink")
                 resource.setInMaint(false)
 
                 //epA is link-name
                 AAIResourceUri logicalLinkUri =
-                        AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().logicalLink(linkName))
+                        AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().logicalLink(epA))
                 getAAIClient().create(logicalLinkUri, resource)
 
-                tnNssmfUtils.attachLogicalLinkToAllottedResource(execution, AAI_VERSION, allottedResourceUri, linkName);
+                tnNssmfUtils.attachLogicalLinkToAllottedResource(execution, tnNssmfUtils.AAI_VERSION,
+                        allottedResourceUri, epA);
             }
         } catch (BpmnError e) {
             throw e
index 45af88d..9440b42 100644 (file)
@@ -24,9 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
 import groovy.json.JsonSlurper
 import org.camunda.bpm.engine.delegate.BpmnError
 import org.camunda.bpm.engine.delegate.DelegateExecution
-import org.onap.aai.domain.yang.ServiceInstance
-import org.onap.aai.domain.yang.SliceProfile
-import org.onap.aaiclient.client.aai.AAIObjectType
+import org.onap.aai.domain.yang.*
 import org.onap.aaiclient.client.aai.AAIResourcesClient
 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
@@ -40,7 +38,7 @@ import org.onap.so.db.request.beans.ResourceOperationStatus
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
-import static org.apache.commons.lang3.StringUtils.isBlank
+import static org.apache.commons.lang3.StringUtils.*
 
 public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
     String Prefix = "TNMOD_"
@@ -70,8 +68,18 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
             logger.debug("SDNC Callback URL: " + execution.getVariable("sdncCallbackUrl"))
 
             String additionalPropJsonStr = execution.getVariable("sliceParams")
+            if (isBlank(additionalPropJsonStr)) {
+                msg = "ERROR: additionalPropJsonStr is null"
+                logger.debug(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
+            }
 
             String sliceServiceInstanceId = execution.getVariable("serviceInstanceID")
+            if (isBlank(sliceServiceInstanceId)) {
+                msg = "ERROR: sliceServiceInstanceId is null"
+                logger.debug(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
+            }
             execution.setVariable("sliceServiceInstanceId", sliceServiceInstanceId)
 
             String sliceServiceInstanceName = execution.getVariable("servicename")
@@ -82,7 +90,10 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
 
             String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
             String modelUuid = execution.getVariable("modelUuid")
-            //here modelVersion is not set, we use modelUuid to decompose the service.
+            if (isEmpty(modelUuid)) {
+                modelUuid = tnNssmfUtils.getModelUuidFromServiceInstance(execution.getVariable("serviceInstanceID"))
+            }
+
             def isDebugLogEnabled = true
             execution.setVariable("isDebugLogEnabled", isDebugLogEnabled)
             String serviceModelInfo = """{
@@ -92,34 +103,15 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
              }"""
             execution.setVariable("serviceModelInfo", serviceModelInfo)
 
-            //additional properties
-            String sliceProfile = jsonUtil.getJsonValue(additionalPropJsonStr, "sliceProfile")
-            if (isBlank(sliceProfile)) {
-                msg = "Input sliceProfile is null"
-                logger.debug(msg)
-                exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
-            } else {
-                execution.setVariable("sliceProfile", sliceProfile)
-            }
+            tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
+                    "sliceProfile", "sliceProfile", true)
 
-            String transportSliceNetworks = jsonUtil.getJsonValue(additionalPropJsonStr, "transportSliceNetworks")
-            if (isBlank(transportSliceNetworks)) {
-                msg = "Input transportSliceNetworks is null"
-                logger.debug(msg)
-                exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
-            } else {
-                execution.setVariable("transportSliceNetworks", transportSliceNetworks)
-            }
-            logger.debug("transportSliceNetworks: " + transportSliceNetworks)
+            tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
+                    "transportSliceNetworks", "transportSliceNetworks", true)
+            logger.debug("transportSliceNetworks: " + execution.getVariable("transportSliceNetworks"))
 
-            String nsiInfo = jsonUtil.getJsonValue(additionalPropJsonStr, "nsiInfo")
-            if (isBlank(nsiInfo)) {
-                msg = "Input nsiInfo is null"
-                logger.debug(msg)
-                exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
-            } else {
-                execution.setVariable("nsiInfo", nsiInfo)
-            }
+            tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
+                    "nsiInfo", "nsiInfo", true)
 
             if (isBlank(tnNssmfUtils.setExecVarFromJsonIfExists(execution, additionalPropJsonStr,
                     "enableSdnc", "enableSdnc"))) {
@@ -152,27 +144,32 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
 
 
     void getExistingServiceInstance(DelegateExecution execution) {
-        String serviceInstanceId = execution.getVariable("serviceInstanceID")
+        String serviceInstanceId = execution.getVariable("sliceServiceInstanceId")
 
         AAIResourcesClient resourceClient = getAAIClient()
         AAIResourceUri ssServiceuri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(serviceInstanceId))
 
         try {
             if (resourceClient.exists(ssServiceuri)) {
-                execution.setVariable("ssi_resourceLink", ssServiceuri.build().toString())
-                org.onap.aai.domain.yang.ServiceInstance ss =
-                        resourceClient.get(org.onap.aai.domain.yang.ServiceInstance.class, ssServiceuri)
-                org.onap.aai.domain.yang.SliceProfile sliceProfile = ss.getSliceProfiles().getSliceProfile().get(0)
-                execution.setVariable("sliceProfileId", sliceProfile.getProfileId())
-
-                org.onap.aai.domain.yang.AllottedResources ars = ss.getAllottedResources()
-                List<org.onap.aai.domain.yang.AllottedResource> arList = ars.getAllottedResource()
+                ServiceInstance ss = resourceClient.get(ServiceInstance.class, ssServiceuri)
+
+                AllottedResources ars = ss.getAllottedResources()
+                List<AllottedResource> arList = ars.getAllottedResource()
                 List<String> arIdList = new ArrayList<>()
-                for (org.onap.aai.domain.yang.AllottedResource ar : arList) {
+                Map<String, String> policyMap = new HashMap<>()
+                Map<String, List<String>> logicalLinksMap = new HashMap<>()
+                for (AllottedResource ar : arList) {
                     String arId = ar.getId()
                     arIdList.add(arId)
+                    String policyId = tnNssmfUtils.getPolicyIdFromAr(execution, serviceInstanceId, arId, true)
+                    policyMap.put(arId, policyId)
+                    List<String> logicalLinkList = tnNssmfUtils.getLogicalLinkNamesFromAr(execution,
+                            serviceInstanceId, arId, true)
+                    logicalLinksMap.put(arId, logicalLinkList)
                 }
                 execution.setVariable("arIdList", arIdList)
+                execution.setVariable("arPolicyMap", policyMap)
+                execution.setVariable("arLogicalLinkMap", logicalLinksMap)
             } else {
                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Service instance was not found in aai to " +
                         "associate allotted resource for service :" + serviceInstanceId)
@@ -184,41 +181,26 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
             logger.debug(msg)
             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
         }
-
     }
 
-    public void updateTnNssiInAAI(DelegateExecution execution) {
+    void updateTnNssiInAAI(DelegateExecution execution) {
         getExistingServiceInstance(execution)
-
-        updateServiceInstance(execution)
-        updateSliceProfile(execution)
-        updateAllottedResource(execution)
+        updateTsciNetworks(execution)
     }
 
     void updateServiceInstance(DelegateExecution execution) {
-        String serviceRole = "TN"
-        String serviceType = execution.getVariable("subscriptionServiceType")
-        String sliceProfileStr = execution.getVariable("sliceProfile")
         String ssInstanceId = execution.getVariable("sliceServiceInstanceId")
         try {
-            org.onap.aai.domain.yang.ServiceInstance ss = new org.onap.aai.domain.yang.ServiceInstance()
-            ss.setServiceInstanceId(ssInstanceId)
-            String sliceInstanceName = execution.getVariable("sliceServiceInstanceName")
-            ss.setServiceInstanceName(sliceInstanceName)
-            ss.setServiceType(serviceType)
+            ServiceInstance ss = new ServiceInstance()
+            //ss.setServiceInstanceId(ssInstanceId)
             String serviceStatus = "modified"
             ss.setOrchestrationStatus(serviceStatus)
-            String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
-            String modelUuid = execution.getVariable("modelUuid")
-            ss.setModelInvariantId(modelInvariantUuid)
-            ss.setModelVersionId(modelUuid)
-            String serviceInstanceLocationid = tnNssmfUtils.getFirstPlmnIdFromSliceProfile(sliceProfileStr)
-            ss.setServiceInstanceLocationId(serviceInstanceLocationid)
-            String snssai = tnNssmfUtils.getFirstSnssaiFromSliceProfile(sliceProfileStr)
-            ss.setEnvironmentContext(snssai)
-            ss.setServiceRole(serviceRole)
             AAIResourcesClient client = getAAIClient()
-            AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("subscriptionServiceType")).serviceInstance(ssInstanceId))
+            AAIResourceUri uri = AAIUriFactory.createResourceUri(
+                    AAIFluentTypeBuilder.business()
+                            .customer(execution.getVariable("globalSubscriberId"))
+                            .serviceSubscription(execution.getVariable("subscriptionServiceType"))
+                            .serviceInstance(ssInstanceId))
             client.update(uri, ss)
         } catch (BpmnError e) {
             throw e
@@ -259,70 +241,180 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
         }
     }
 
-    void updateAllottedResource(DelegateExecution execution) {
-        String serviceInstanceId = execution.getVariable('serviceInstanceID')
-
+    String getValidArId(DelegateExecution execution, String arIdStr) {
         List<String> arIdList = execution.getVariable("arIdList")
+        /*
+         * If arId is not specified by the caller, then we assume the caller
+         * wants to modify the first network (i.e., allotted resource) in the TSCi tree.
+         */
+        String arId = isBlank(arIdStr) ? arIdList.get(0) : arIdStr
+
+        return arId
+    }
+
+    void updateLogicalLinksInAr(DelegateExecution execution, String arId, String linkArrayJsonStr) {
         try {
-            for (String arId : arIdList) {
-                AAIResourceUri arUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("subscriptionServiceType")).serviceInstance(serviceInstanceId).allottedResource(arId))
+            String serviceInstanceId = execution.getVariable('sliceServiceInstanceId')
+
+            /*
+             * Each TSCi connection-link in linkArrayJsonStr is considered as an "ADD" new
+             * link to allotted-resource. So, if the link already exists under AR, then do
+             * nothing. Otherwise, create logical-link.
+             */
+            List<String> linkStrList = jsonUtil.StringArrayToList(linkArrayJsonStr)
+            for (String linkStr : linkStrList) {
+                if (logicalLinkExists(execution, arId, linkStr)) {
+                    continue
+                }
 
-                getAAIClient().delete(arUri)
+                createLogicalLinkForAllocatedResource(execution, linkStr, serviceInstanceId, arId)
             }
+        } catch (BpmnError e) {
+            throw e
+        } catch (Exception ex) {
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
+                    "Exception in updateLogicalLinksInAr" + ex.getMessage())
+        }
+    }
 
-            List<String> networkStrList = jsonUtil.StringArrayToList(execution.getVariable("transportSliceNetworks"))
+    void updateLogicalLinksInNetwork(DelegateExecution execution, String networkJsonStr) {
+        try {
+            String arId = getValidArId(jsonUtil.getJsonValue(networkJsonStr, "id"))
+            String linkArrayStr = jsonUtil.getJsonValue(networkJsonStr, "connectionLinks")
+            updateLogicalLinksInAr(execution, arId, linkArrayStr)
+        } catch (BpmnError e) {
+            throw e
+        } catch (Exception ex) {
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
+                    "Exception in updateLogicalLinksInNetwork" + ex.getMessage())
+        }
+    }
 
+    void updateTsciNetworks(DelegateExecution execution) {
+        try {
+            List<String> networkStrList = jsonUtil.StringArrayToList(execution.getVariable("transportSliceNetworks"))
             for (String networkStr : networkStrList) {
-                String allottedResourceId = UUID.randomUUID().toString()
-                AAIResourceUri allottedResourceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("subscriptionServiceType")).serviceInstance(execution.getVariable("sliceserviceInstanceId")).allottedResource(allottedResourceId))
-                execution.setVariable("allottedResourceUri", allottedResourceUri)
-                String modelInvariantId = execution.getVariable("modelInvariantUuid")
-                String modelVersionId = execution.getVariable("modelUuid")
-
-                org.onap.aai.domain.yang.AllottedResource resource = new org.onap.aai.domain.yang.AllottedResource()
-                resource.setId(allottedResourceId)
-                resource.setType("TsciNetwork")
-                resource.setAllottedResourceName("network_" + execution.getVariable("sliceServiceInstanceName"))
-                resource.setModelInvariantId(modelInvariantId)
-                resource.setModelVersionId(modelVersionId)
-                getAAIClient().create(allottedResourceUri, resource)
-
-                String linkArrayStr = jsonUtil.getJsonValue(networkStr, "connectionLinks")
-                createLogicalLinksForAllocatedResource(execution, linkArrayStr, serviceInstanceId, allottedResourceId)
+                updateLogicalLinksInNetwork(execution, networkStr)
+                updateNetworkPolicy(execution, networkStr)
             }
 
+        } catch (BpmnError e) {
+            throw e
         } catch (Exception ex) {
-            exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Exception in createAaiAR " + ex.getMessage())
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
+                    "Exception in updateTsciNetworks" + ex.getMessage())
         }
     }
 
-    void createLogicalLinksForAllocatedResource(DelegateExecution execution,
-                                                String linkArrayStr, String serviceInstanceId,
-                                                String allottedResourceId) {
+    int getMaxBw(DelegateExecution execution) {
+        int maxBw = 0
+        try {
+            String sliceProfileStr = execution.getVariable("sliceProfile")
+            if (isBlank(sliceProfileStr)) {
+                String msg = "ERROR: getMaxBw: sliceProfile is null"
+                logger.error(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
+            }
+            String bwStr = jsonUtil.getJsonValue(sliceProfileStr, "maxBandwidth")
+            if (isNotBlank(bwStr)) {
+                maxBw = Integer.parseInt(bwStr)
+            } else {
+                logger.error("ERROR: getMaxBw: maxBandwidth is null")
+            }
+        } catch (BpmnError e) {
+            throw e
+        } catch (Exception ex) {
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
+                    "Exception in getMaxBw" + ex.getMessage())
+        }
+
+        return maxBw
+    }
 
+    void updatePolicyMaxBandwidthInAAI(DelegateExecution execution, String policyId, int maxBw) {
         try {
-            List<String> linkStrList = jsonUtil.StringArrayToList(linkArrayStr)
+            NetworkPolicy networkPolicy = new NetworkPolicy()
+            networkPolicy.setMaxBandwidth(maxBw)
+            AAIResourceUri networkPolicyUri =
+                    AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().networkPolicy(policyId))
+            getAAIClient().update(networkPolicyUri, networkPolicy)
+        } catch (BpmnError e) {
+            throw e
+        } catch (Exception ex) {
+            String msg = "Exception in DoCreateTnNssiInstance.createServiceInstance. " + ex.getMessage()
+            logger.info(msg)
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
+        }
+    }
 
-            for (String linkStr : linkStrList) {
-                String logicalLinkId = UUID.randomUUID().toString()
-                String epA = jsonUtil.getJsonValue(linkStr, "transportEndpointA")
-                String epB = jsonUtil.getJsonValue(linkStr, "transportEndpointB")
-                String modelInvariantId = execution.getVariable("modelInvariantUuid")
-                String modelVersionId = execution.getVariable("modelUuid")
-
-                org.onap.aai.domain.yang.LogicalLink resource = new org.onap.aai.domain.yang.LogicalLink()
-                resource.setLinkId(logicalLinkId)
-                resource.setLinkName(epA)
-                resource.setLinkName2(epB)
-                resource.setModelInvariantId(modelInvariantId)
-                resource.setModelVersionId(modelVersionId)
-
-                AAIResourceUri logicalLinkUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().logicalLink(logicalLinkId))
-                getAAIClient().create(logicalLinkUri, resource)
+    void updateNetworkPolicy(DelegateExecution execution, String networkJsonStr) {
+        try {
+            int maxBw = getMaxBw(execution)
+
+            String arId = getValidArId(jsonUtil.getJsonValue(networkJsonStr, "id"))
+            Map<String, String> policyMap = execution.getVariable("arPolicyMap")
+            String policyId = policyMap.get(arId)
+            if (isBlank(policyId)) {
+                String msg = String.format("ERROR: updateNetworkPolicy: policyId not found. arId=%s", arId)
+                logger.error(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
             }
+
+            updatePolicyMaxBandwidthInAAI(execution, policyId, maxBw)
+
+        } catch (BpmnError e) {
+            throw e
         } catch (Exception ex) {
             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
-                    "Exception in createLogicalLinksForAllocatedResource" + ex.getMessage())
+                    "Exception in updateNetworkPolicy" + ex.getMessage())
+        }
+    }
+
+
+    void createLogicalLinkForAllocatedResource(DelegateExecution execution,
+                                               String linkJsonStr, String ssInstanceId,
+                                               String allottedResourceId) {
+        try {
+            AAIResourceUri allottedResourceUri = tnNssmfUtils.buildAllottedResourceUri(execution,
+                    ssInstanceId, allottedResourceId)
+
+            if (!getAAIClient().exists(allottedResourceUri)) {
+                logger.info("ERROR: createLogicalLinksForAllocatedResource: allottedResource not exist: uri={}",
+                        allottedResourceUri)
+                return
+            }
+
+            String linkId = jsonUtil.getJsonValue(linkJsonStr, "id")
+            if (isBlank(linkId)) {
+                linkId = "tn-nssmf-" + UUID.randomUUID().toString()
+            }
+            logger.debug("createLogicalLinkForAllocatedResource: linkId=" + linkId)
+
+            String epA = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointA")
+            String epB = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointB")
+            String modelInvariantId = execution.getVariable("modelInvariantUuid")
+            String modelVersionId = execution.getVariable("modelUuid")
+
+            org.onap.aai.domain.yang.LogicalLink resource = new org.onap.aai.domain.yang.LogicalLink()
+            resource.setLinkId(linkId)
+            resource.setLinkName(epA)
+            resource.setLinkName2(epB)
+            resource.setLinkType("TsciConnectionLink")
+            resource.setInMaint(false)
+
+            //epA is link-name
+            AAIResourceUri logicalLinkUri =
+                    AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().logicalLink(epA))
+            getAAIClient().create(logicalLinkUri, resource)
+
+            tnNssmfUtils.attachLogicalLinkToAllottedResource(execution, tnNssmfUtils.AAI_VERSION,
+                    allottedResourceUri, epA);
+        } catch (BpmnError e) {
+            throw e
+        } catch (Exception ex) {
+            String msg = "Exception in DoCreateTnNssiInstance.createLogicalLinksForAllocatedResource: " + ex.getMessage()
+            logger.error(msg)
+            exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
         }
     }
 
@@ -334,13 +426,15 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
         logger.trace('Entered ' + method)
 
         try {
-            String serviceInstanceId = execution.getVariable("serviceInstanceID")
+            String serviceInstanceId = execution.getVariable("sliceServiceInstanceId")
 
             String sdncRequest = tnNssmfUtils.buildSDNCRequest(execution, serviceInstanceId, "modify")
 
             execution.setVariable("TNNSSMF_SDNCRequest", sdncRequest)
             logger.debug("Outgoing SDNCRequest is: \n" + sdncRequest)
 
+        } catch (BpmnError e) {
+            throw e
         } catch (Exception e) {
             logger.debug("Exception Occured Processing preprocessSdncModifyTnNssiRequest. Exception is:\n" + e)
             exceptionUtil.buildAndThrowWorkflowException(execution, 1002, "Error Occured during  preProcessSDNCActivateRequest Method:\n" + e.getMessage())
@@ -380,20 +474,47 @@ public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
                                 String status,
                                 String progress,
                                 String statusDescription) {
-        String serviceId = execution.getVariable("serviceInstanceID")
+        String ssInstanceId = execution.getVariable("sliceServiceInstanceId")
+        String modelUuid = execution.getVariable("modelUuid")
         String jobId = execution.getVariable("jobId")
         String nsiId = execution.getVariable("nsiId")
+        String operType = "MODIFY"
+
+        ResourceOperationStatus roStatus = tnNssmfUtils.buildRoStatus(modelUuid, ssInstanceId,
+                jobId, nsiId, operType, status, progress, statusDescription)
 
-        ResourceOperationStatus roStatus = new ResourceOperationStatus()
-        roStatus.setServiceId(serviceId)
-        roStatus.setOperationId(jobId)
-        roStatus.setResourceTemplateUUID(nsiId)
-        roStatus.setOperType("Modify")
-        roStatus.setProgress(progress)
-        roStatus.setStatus(status)
-        roStatus.setStatusDescription(statusDescription)
         requestDBUtil.prepareUpdateResourceOperationStatus(execution, roStatus)
     }
 
+    boolean logicalLinkExists(DelegateExecution execution, String arIdStr, String linkJsonStr) {
+        if (isBlank(arIdStr)) {
+            logger.error("ERROR: logicalLinkExists: arIdStr is empty")
+            return false
+        }
+        if (isBlank(linkJsonStr)) {
+            logger.error("ERROR: logicalLinkExists: linkJsonStr is empty")
+            return false
+        }
+
+        Map<String, List<String>> logicalLinksMap = execution.getVariable("arLogicalLinkMap")
+        if (logicalLinksMap == null) {
+            logger.error("ERROR: logicalLinkExists: logicalLinksMap is null")
+            return false
+        }
+
+        List<String> logicalLinkNameList = logicalLinksMap.get(arIdStr)
+        if (logicalLinksMap == null) {
+            logger.error("ERROR: logicalLinkExists: logicalLinkNameList is null. arIdStr=" + arIdStr)
+            return false
+        }
+
+        String linkName = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointA")
+        if (isBlank(linkName)) {
+            logger.error("ERROR: logicalLinkExists: epA is empty")
+            return false
+        }
+
+        return logicalLinkNameList.contains(linkName)
+    }
 }
 
index 4877a23..4624cda 100644 (file)
@@ -22,12 +22,17 @@ package org.onap.so.bpmn.infrastructure.scripts
 
 import org.camunda.bpm.engine.delegate.BpmnError
 import org.camunda.bpm.engine.delegate.DelegateExecution
+import org.onap.aai.domain.yang.LogicalLink
+import org.onap.aai.domain.yang.NetworkPolicy
 import org.onap.aai.domain.yang.Relationship
 import org.onap.aai.domain.yang.ServiceInstance
 import org.onap.aaiclient.client.aai.AAIResourcesClient
+import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
+import org.onap.aaiclient.client.aai.entities.Relationships
 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
+import org.onap.aaiclient.client.generated.fluentbuilders.Activities
 import org.onap.so.bpmn.common.scripts.ExceptionUtil
 import org.onap.so.bpmn.common.scripts.MsoUtils
 import org.onap.so.bpmn.common.scripts.SDNCAdapterUtils
@@ -42,6 +47,7 @@ import org.slf4j.LoggerFactory
 import static org.apache.commons.lang3.StringUtils.isBlank
 
 class TnNssmfUtils {
+    static final String AAI_VERSION = "v23"
     private static final Logger logger = LoggerFactory.getLogger(TnNssmfUtils.class);
 
 
@@ -429,4 +435,115 @@ class TnNssmfUtils {
 
         return si.modelVersionId()
     }
+
+    AAIResourceUri buildNetworkPolicyUri(String networkPolicyId) {
+        AAIResourceUri networkPolicyUri =
+                AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().networkPolicy(networkPolicyId))
+
+        return networkPolicyUri
+    }
+
+    AAIResourceUri buildAllottedResourceUri(DelegateExecution execution, String serviceInstanceId,
+                                            String allottedResourceId) {
+
+        AAIResourceUri allottedResourceUri =
+                AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
+                        .customer(execution.getVariable("globalSubscriberId"))
+                        .serviceSubscription(execution.getVariable("subscriptionServiceType"))
+                        .serviceInstance(serviceInstanceId)
+                        .allottedResource(allottedResourceId))
+
+        return allottedResourceUri
+    }
+
+
+    String getPolicyIdFromAr(DelegateExecution execution, String serviceInstanceId,
+                             String arId, boolean exceptionOnErr) {
+        String res
+        try {
+            AAIResourcesClient client = new AAIResourcesClient()
+
+            AAIResourceUri arUri = buildAllottedResourceUri(execution, serviceInstanceId, arId)
+            List<AAIResourceUri> logicalLinkUriList = getRelationshipUriListInAai(execution, arUri,
+                    AAIFluentTypeBuilder.Types.NETWORK_POLICY, exceptionOnErr)
+            for (AAIResourceUri logicalLinkUri : logicalLinkUriList) {
+                Optional<NetworkPolicy> policyOpt = client.get(NetworkPolicy.class, logicalLinkUri)
+                if (policyOpt.isPresent()) {
+                    NetworkPolicy policy = policyOpt.get()
+                    return policy.getNetworkPolicyId()
+                } else {
+                    String msg = String.format("ERROR: getLogicalLinkNamesFromAr: logicalLinkUri=%s", logicalLinkUri)
+                    logger.error(msg)
+                    exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
+                }
+            }
+        } catch (BpmnError e) {
+            if (exceptionOnErr) {
+                throw e;
+            }
+        } catch (Exception ex) {
+            if (exceptionOnErr) {
+                String msg = String.format("ERROR: getLogicalLinkNamesFromAr: %s", ex.getMessage())
+                logger.error(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
+            }
+        }
+
+        return res
+    }
+
+
+    List<AAIResourceUri> getRelationshipUriListInAai(DelegateExecution execution,
+                                                     AAIResourceUri uri, Activities.Info info,
+                                                     boolean exceptionOnErr) {
+        AAIResourcesClient client = new AAIResourcesClient()
+        AAIResultWrapper wrapper = client.get(uri);
+        Optional<Relationships> relationships = wrapper.getRelationships()
+        if (relationships.isPresent()) {
+            return relationships.get().getRelatedUris(info)
+        } else {
+            if (exceptionOnErr) {
+                String msg = "ERROR: getRelationshipUriListInAai: No relationship found"
+                logger.error(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
+            }
+        }
+
+        return null
+    }
+
+    List<String> getLogicalLinkNamesFromAr(DelegateExecution execution, String serviceInstanceId,
+                                           String arId, boolean exceptionOnErr) {
+        List<String> res = new ArrayList<>()
+        try {
+            AAIResourcesClient client = new AAIResourcesClient()
+
+            AAIResourceUri arUri = buildAllottedResourceUri(execution, serviceInstanceId, arId)
+            List<AAIResourceUri> logicalLinkUriList = getRelationshipUriListInAai(execution, arUri,
+                    AAIFluentTypeBuilder.Types.LOGICAL_LINK, exceptionOnErr)
+            for (AAIResourceUri logicalLinkUri : logicalLinkUriList) {
+                Optional<LogicalLink> logicalLinkOpt = client.get(LogicalLink.class, logicalLinkUri)
+                if (logicalLinkOpt.isPresent()) {
+                    LogicalLink logicalLink = logicalLinkOpt.get()
+                    res.add(logicalLink.getLinkName())
+                } else {
+                    String msg = String.format("ERROR: getLogicalLinkNamesFromAr: logicalLinkUri=%s", logicalLinkUri)
+                    logger.error(msg)
+                    exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
+                }
+            }
+        } catch (BpmnError e) {
+            if (exceptionOnErr) {
+                throw e;
+            }
+        } catch (Exception ex) {
+            if (exceptionOnErr) {
+                String msg = String.format("ERROR: getLogicalLinkNamesFromAr: %s", ex.getMessage())
+                logger.error(msg)
+                exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
+            }
+        }
+
+        return res
+    }
 }
\ No newline at end of file
index 2b122fb..dcfd31b 100644 (file)
@@ -36,6 +36,7 @@ runScript.prepareUpdateJobStatus(execution,"FINISHED","100","Modified TN NSSI su
     <bpmn:sequenceFlow id="SequenceFlow_1qv8qw1" sourceRef="ScriptTask_1ssh2l9" targetRef="Activity_0ziz3ti" />
     <bpmn:scriptTask id="ScriptTask_19uxoi8" name="Update AAI Status" scriptFormat="groovy">
       <bpmn:incoming>Flow_0h5rwlh</bpmn:incoming>
+      <bpmn:incoming>Flow_0b3rxne</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_0kixzdj</bpmn:outgoing>
       <bpmn:script>import org.onap.so.bpmn.infrastructure.scripts.*
 execution.setVariable("orchestrationStatus", "modified")
@@ -51,7 +52,7 @@ runScript.updateAAIOrchStatus(execution)</bpmn:script>
 def runScript = new DoModifyTnNssi()
 runScript.updateTnNssiInAAI(execution)</bpmn:script>
     </bpmn:scriptTask>
-    <bpmn:sequenceFlow id="SequenceFlow_1jdb2oq" sourceRef="Activity_0phv8e5" targetRef="Activity_0h1vr2l" />
+    <bpmn:sequenceFlow id="SequenceFlow_1jdb2oq" sourceRef="Activity_0phv8e5" targetRef="Gateway_1o68a9z" />
     <bpmn:scriptTask id="ScriptTask_1tc44ge" name="PreProcess Incoming Request" scriptFormat="groovy">
       <bpmn:incoming>SequenceFlow_03s744c</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_07e12rt</bpmn:outgoing>
@@ -61,7 +62,7 @@ runScript.preProcessRequest(execution)</bpmn:script>
     </bpmn:scriptTask>
     <bpmn:sequenceFlow id="SequenceFlow_07e12rt" sourceRef="ScriptTask_1tc44ge" targetRef="Activity_0phv8e5" />
     <bpmn:scriptTask id="Activity_0h1vr2l" name="PreProcess SDNC Modify  TN NSSI Request" scriptFormat="groovy">
-      <bpmn:incoming>SequenceFlow_1jdb2oq</bpmn:incoming>
+      <bpmn:incoming>Flow_0cm9i4m</bpmn:incoming>
       <bpmn:outgoing>Flow_1dvo5ih</bpmn:outgoing>
       <bpmn:script>import org.onap.so.bpmn.infrastructure.scripts.*
 def runScript = new DoModifyTnNssi()
@@ -116,106 +117,135 @@ runScript.validateSDNCResponse(execution, response, "modify")</bpmn:script>
       <bpmn:outgoing>Flow_1akxvak</bpmn:outgoing>
     </bpmn:serviceTask>
     <bpmn:sequenceFlow id="Flow_1akxvak" sourceRef="Activity_0ziz3ti" targetRef="EndEvent_05h01gx" />
+    <bpmn:exclusiveGateway id="Gateway_1o68a9z" name="Enable SDNC?">
+      <bpmn:incoming>SequenceFlow_1jdb2oq</bpmn:incoming>
+      <bpmn:outgoing>Flow_0cm9i4m</bpmn:outgoing>
+      <bpmn:outgoing>Flow_0b3rxne</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:sequenceFlow id="Flow_0cm9i4m" name="Yes" sourceRef="Gateway_1o68a9z" targetRef="Activity_0h1vr2l">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{(execution.getVariable("enableSdnc" )  == true)}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="Flow_0b3rxne" name="No" sourceRef="Gateway_1o68a9z" targetRef="ScriptTask_19uxoi8" />
   </bpmn:process>
   <bpmn:message id="Message_0c4b2r5" name="SliceServiceTask" />
   <bpmn:error id="Error_03akl5v" name="MSOWorkflowException" errorCode="MSOWorkflowException" />
   <bpmn:error id="Error_0p2naox" name="MSOWorkflowException" errorCode="MSOWorkflowException" />
   <bpmndi:BPMNDiagram id="BPMNDiagram_1">
     <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="DoModifyTransportNSSI">
+      <bpmndi:BPMNEdge id="Flow_1akxvak_di" bpmnElement="Flow_1akxvak">
+        <di:waypoint x="1230" y="400" />
+        <di:waypoint x="1372" y="400" />
+      </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="Flow_0h5rwlh_di" bpmnElement="Flow_0h5rwlh">
-        <di:waypoint x="1240" y="121" />
-        <di:waypoint x="1380" y="121" />
-        <di:waypoint x="1380" y="210" />
-        <di:waypoint x="335" y="210" />
-        <di:waypoint x="335" y="310" />
+        <di:waypoint x="1350" y="121" />
+        <di:waypoint x="1430" y="121" />
+        <di:waypoint x="1430" y="280" />
+        <di:waypoint x="690" y="280" />
+        <di:waypoint x="690" y="360" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="Flow_139j3yd_di" bpmnElement="Flow_139j3yd">
-        <di:waypoint x="1010" y="121" />
-        <di:waypoint x="1119" y="121" />
+        <di:waypoint x="1110" y="121" />
+        <di:waypoint x="1229" y="121" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="Flow_1dvo5ih_di" bpmnElement="Flow_1dvo5ih">
-        <di:waypoint x="806" y="121" />
-        <di:waypoint x="889" y="121" />
+        <di:waypoint x="910" y="121" />
+        <di:waypoint x="989" y="121" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_07e12rt_di" bpmnElement="SequenceFlow_07e12rt">
-        <di:waypoint x="385" y="121" />
+        <di:waypoint x="390" y="121" />
         <di:waypoint x="479" y="121" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="Flow_1jdb2oq_di" bpmnElement="SequenceFlow_1jdb2oq">
         <di:waypoint x="600" y="121" />
-        <di:waypoint x="685" y="121" />
+        <di:waypoint x="665" y="121" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_0kixzdj_di" bpmnElement="SequenceFlow_0kixzdj">
-        <di:waypoint x="385" y="350" />
-        <di:waypoint x="530" y="350" />
+        <di:waypoint x="740" y="400" />
+        <di:waypoint x="860" y="400" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_1qv8qw1_di" bpmnElement="SequenceFlow_1qv8qw1">
-        <di:waypoint x="630" y="350" />
-        <di:waypoint x="740" y="350" />
+        <di:waypoint x="960" y="400" />
+        <di:waypoint x="1130" y="400" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="SequenceFlow_03s744c_di" bpmnElement="SequenceFlow_03s744c">
-        <di:waypoint x="214" y="121" />
-        <di:waypoint x="285" y="121" />
+        <di:waypoint x="208" y="121" />
+        <di:waypoint x="290" y="121" />
       </bpmndi:BPMNEdge>
-      <bpmndi:BPMNEdge id="Flow_1akxvak_di" bpmnElement="Flow_1akxvak">
-        <di:waypoint x="840" y="350" />
-        <di:waypoint x="1002" y="350" />
+      <bpmndi:BPMNEdge id="Flow_0cm9i4m_di" bpmnElement="Flow_0cm9i4m">
+        <di:waypoint x="715" y="121" />
+        <di:waypoint x="789" y="121" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="743" y="103" width="19" height="14" />
+        </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
-      <bpmndi:BPMNShape id="StartEvent_1nbljfd_di" bpmnElement="StartEvent_1nbljfd">
-        <dc:Bounds x="178" y="103" width="36" height="36" />
+      <bpmndi:BPMNEdge id="Flow_0b3rxne_di" bpmnElement="Flow_0b3rxne">
+        <di:waypoint x="690" y="146" />
+        <di:waypoint x="690" y="360" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="161" y="146" width="86" height="40" />
+          <dc:Bounds x="698" y="203" width="15" height="14" />
         </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Activity_1vtz33q_di" bpmnElement="Activity_1vtz33q">
+        <dc:Bounds x="1229" y="74" width="121" height="94" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="Activity_0ziz3ti_di" bpmnElement="Activity_0ziz3ti">
-        <dc:Bounds x="740" y="310" width="100" height="80" />
+      <bpmndi:BPMNShape id="Activity_14ab476_di" bpmnElement="Activity_14ab476">
+        <dc:Bounds x="989" y="74" width="121" height="94" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="SubProcess_1yv9i68_di" bpmnElement="SubProcess_1yv9i68" isExpanded="true">
-        <dc:Bounds x="685" y="1080" width="781" height="196" />
+      <bpmndi:BPMNShape id="Activity_0h1vr2l_di" bpmnElement="Activity_0h1vr2l">
+        <dc:Bounds x="789" y="74" width="121" height="94" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNEdge id="SequenceFlow_08mlzwz_di" bpmnElement="SequenceFlow_08mlzwz">
-        <di:waypoint x="1079" y="1184" />
-        <di:waypoint x="1353" y="1184" />
-      </bpmndi:BPMNEdge>
-      <bpmndi:BPMNEdge id="SequenceFlow_1w67v6s_di" bpmnElement="SequenceFlow_1w67v6s">
-        <di:waypoint x="751" y="1184" />
-        <di:waypoint x="979" y="1184" />
-      </bpmndi:BPMNEdge>
-      <bpmndi:BPMNShape id="StartEvent_1omdx56_di" bpmnElement="StartEvent_1omdx56">
-        <dc:Bounds x="715" y="1166" width="36" height="36" />
+      <bpmndi:BPMNShape id="StartEvent_1nbljfd_di" bpmnElement="StartEvent_1nbljfd">
+        <dc:Bounds x="172" y="103" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="155" y="146" width="86" height="40" />
+        </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="EndEvent_1jx3026_di" bpmnElement="EndEvent_1jx3026">
-        <dc:Bounds x="1353" y="1166" width="36" height="36" />
+      <bpmndi:BPMNShape id="ScriptTask_1tc44ge_di" bpmnElement="ScriptTask_1tc44ge">
+        <dc:Bounds x="290" y="81" width="100" height="80" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="ScriptTask_1swzdpw_di" bpmnElement="ScriptTask_1swzdpw">
-        <dc:Bounds x="979" y="1144" width="100" height="80" />
+      <bpmndi:BPMNShape id="Activity_0phv8e5_di" bpmnElement="Activity_0phv8e5">
+        <dc:Bounds x="479" y="74" width="121" height="94" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="EndEvent_05h01gx_di" bpmnElement="EndEvent_05h01gx">
-        <dc:Bounds x="1002" y="332" width="36" height="36" />
+      <bpmndi:BPMNShape id="Gateway_1o68a9z_di" bpmnElement="Gateway_1o68a9z" isMarkerVisible="true">
+        <dc:Bounds x="665" y="96" width="50" height="50" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="1010" y="375" width="20" height="14" />
+          <dc:Bounds x="653" y="73" width="75" height="14" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ScriptTask_19uxoi8_di" bpmnElement="ScriptTask_19uxoi8">
+        <dc:Bounds x="640" y="360" width="100" height="80" />
+      </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="ScriptTask_1ssh2l9_di" bpmnElement="ScriptTask_1ssh2l9">
-        <dc:Bounds x="530" y="310" width="100" height="80" />
+        <dc:Bounds x="860" y="360" width="100" height="80" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="ScriptTask_19uxoi8_di" bpmnElement="ScriptTask_19uxoi8">
-        <dc:Bounds x="285" y="310" width="100" height="80" />
+      <bpmndi:BPMNShape id="Activity_0ziz3ti_di" bpmnElement="Activity_0ziz3ti">
+        <dc:Bounds x="1130" y="360" width="100" height="80" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="Activity_0phv8e5_di" bpmnElement="Activity_0phv8e5">
-        <dc:Bounds x="479" y="74" width="121" height="94" />
+      <bpmndi:BPMNShape id="EndEvent_05h01gx_di" bpmnElement="EndEvent_05h01gx">
+        <dc:Bounds x="1372" y="382" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1380" y="425" width="20" height="14" />
+        </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="ScriptTask_1tc44ge_di" bpmnElement="ScriptTask_1tc44ge">
-        <dc:Bounds x="285" y="81" width="100" height="80" />
+      <bpmndi:BPMNShape id="SubProcess_1yv9i68_di" bpmnElement="SubProcess_1yv9i68" isExpanded="true">
+        <dc:Bounds x="735" y="1080" width="781" height="196" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="Activity_0h1vr2l_di" bpmnElement="Activity_0h1vr2l">
-        <dc:Bounds x="685" y="74" width="121" height="94" />
+      <bpmndi:BPMNEdge id="SequenceFlow_08mlzwz_di" bpmnElement="SequenceFlow_08mlzwz">
+        <di:waypoint x="1129" y="1184" />
+        <di:waypoint x="1403" y="1184" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1w67v6s_di" bpmnElement="SequenceFlow_1w67v6s">
+        <di:waypoint x="801" y="1184" />
+        <di:waypoint x="1029" y="1184" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="StartEvent_1omdx56_di" bpmnElement="StartEvent_1omdx56">
+        <dc:Bounds x="765" y="1166" width="36" height="36" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="Activity_14ab476_di" bpmnElement="Activity_14ab476">
-        <dc:Bounds x="889" y="74" width="121" height="94" />
+      <bpmndi:BPMNShape id="EndEvent_1jx3026_di" bpmnElement="EndEvent_1jx3026">
+        <dc:Bounds x="1403" y="1166" width="36" height="36" />
       </bpmndi:BPMNShape>
-      <bpmndi:BPMNShape id="Activity_1vtz33q_di" bpmnElement="Activity_1vtz33q">
-        <dc:Bounds x="1119" y="74" width="121" height="94" />
+      <bpmndi:BPMNShape id="ScriptTask_1swzdpw_di" bpmnElement="ScriptTask_1swzdpw">
+        <dc:Bounds x="1029" y="1144" width="100" height="80" />
       </bpmndi:BPMNShape>
     </bpmndi:BPMNPlane>
   </bpmndi:BPMNDiagram>