summaryrefslogtreecommitdiffstats
path: root/bpmn/MSOCommonBPMN/src
diff options
context:
space:
mode:
Diffstat (limited to 'bpmn/MSOCommonBPMN/src')
-rw-r--r--bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetup.java96
-rw-r--r--bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtils.java18
-rw-r--r--bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundException.java15
-rw-r--r--bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupTest.java82
-rw-r--r--bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtilsTest.java31
-rw-r--r--bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundExceptionTest.java19
6 files changed, 218 insertions, 43 deletions
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetup.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetup.java
index b4c5ca9a7e..7e982369bb 100644
--- a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetup.java
+++ b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetup.java
@@ -62,6 +62,7 @@ import org.onap.so.bpmn.servicedecomposition.entities.WorkflowResourceIds;
import org.onap.so.bpmn.servicedecomposition.generalobjects.OrchestrationContext;
import org.onap.so.bpmn.servicedecomposition.generalobjects.RequestContext;
import org.onap.so.bpmn.servicedecomposition.tasks.exceptions.NoServiceInstanceFoundException;
+import org.onap.so.bpmn.servicedecomposition.tasks.exceptions.ServiceModelNotFoundException;
import org.onap.so.client.aai.AAICommonObjectMapperProvider;
import org.onap.so.client.aai.AAIObjectType;
import org.onap.so.client.aai.entities.AAIResultWrapper;
@@ -253,41 +254,46 @@ public class BBInputSetup implements JavaDelegate {
String bbName = executeBB.getBuildingBlock().getBpmnFlowName();
String serviceInstanceId = lookupKeyMap.get(ResourceKey.SERVICE_INSTANCE_ID);
org.onap.aai.domain.yang.ServiceInstance aaiServiceInstance = null;
- if (serviceInstanceId != null) {
- aaiServiceInstance = bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId);
- }
Service service = null;
boolean isReplace = false;
- if (aaiServiceInstance != null) {
- if (requestAction.equalsIgnoreCase("replaceInstance")) {
- RelatedInstanceList[] relatedInstanceList = requestDetails.getRelatedInstanceList();
- if (relatedInstanceList != null) {
- for (RelatedInstanceList relatedInstList : relatedInstanceList) {
- RelatedInstance relatedInstance = relatedInstList.getRelatedInstance();
- if (relatedInstance.getModelInfo().getModelType().equals(ModelType.service)) {
- service = bbInputSetupUtils
- .getCatalogServiceByModelUUID(relatedInstance.getModelInfo().getModelVersionId());
- isReplace = true;
+ if (serviceInstanceId != null) {
+ aaiServiceInstance = bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId);
+ if (aaiServiceInstance != null) {
+ if (requestAction.equalsIgnoreCase("replaceInstance")) {
+ RelatedInstanceList[] relatedInstanceList = requestDetails.getRelatedInstanceList();
+ if (relatedInstanceList != null) {
+ for (RelatedInstanceList relatedInstList : relatedInstanceList) {
+ RelatedInstance relatedInstance = relatedInstList.getRelatedInstance();
+ if (relatedInstance.getModelInfo().getModelType().equals(ModelType.service)) {
+ service = bbInputSetupUtils.getCatalogServiceByModelUUID(
+ relatedInstance.getModelInfo().getModelVersionId());
+ isReplace = true;
+ }
}
}
+ } else {
+ service = bbInputSetupUtils.getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
+ }
+ if (service == null) {
+ String message = String.format(
+ "Related service instance model not found in MSO CatalogDB: model-version-id=%s",
+ aaiServiceInstance.getModelVersionId());
+ throw new ServiceModelNotFoundException(message);
}
} else {
- service = bbInputSetupUtils.getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
+ String message = String.format("Related service instance from AAI not found: service-instance-id=%s",
+ serviceInstanceId);
+ throw new NoServiceInstanceFoundException(message);
}
}
- if (aaiServiceInstance != null && service != null) {
- ServiceInstance serviceInstance = this.getExistingServiceInstance(aaiServiceInstance);
- serviceInstance.setModelInfoServiceInstance(this.mapperLayer.mapCatalogServiceIntoServiceInstance(service));
- this.populateObjectsOnAssignAndCreateFlows(executeBB.getRequestId(), requestDetails, service, bbName,
- serviceInstance, lookupKeyMap, resourceId, vnfType, executeBB.getBuildingBlock().getKey(),
- executeBB.getConfigurationResourceKeys(), isReplace);
- return this.populateGBBWithSIAndAdditionalInfo(requestDetails, serviceInstance, executeBB, requestAction,
- null);
- } else {
- logger.debug("Related Service Instance from AAI: {}", aaiServiceInstance);
- logger.debug("Related Service Instance Model Info from AAI: {}", service);
- throw new Exception("Could not find relevant information for related Service Instance");
- }
+
+ ServiceInstance serviceInstance = this.getExistingServiceInstance(aaiServiceInstance);
+ serviceInstance.setModelInfoServiceInstance(this.mapperLayer.mapCatalogServiceIntoServiceInstance(service));
+ this.populateObjectsOnAssignAndCreateFlows(executeBB.getRequestId(), requestDetails, service, bbName,
+ serviceInstance, lookupKeyMap, resourceId, vnfType, executeBB.getBuildingBlock().getKey(),
+ executeBB.getConfigurationResourceKeys(), isReplace);
+ return this.populateGBBWithSIAndAdditionalInfo(requestDetails, serviceInstance, executeBB, requestAction, null);
+
}
protected GeneralBuildingBlock getGBBCM(ExecuteBuildingBlock executeBB, RequestDetails requestDetails,
@@ -1285,24 +1291,30 @@ public class BBInputSetup implements JavaDelegate {
String serviceInstanceId = lookupKeyMap.get(ResourceKey.SERVICE_INSTANCE_ID);
RequestDetails requestDetails = executeBB.getRequestDetails();
GeneralBuildingBlock gBB = null;
+ Service service = null;
if (serviceInstanceId != null) {
aaiServiceInstance = bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId);
+ if (aaiServiceInstance != null) {
+ service = bbInputSetupUtils.getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
+ if (service == null) {
+ String message = String.format(
+ "Related service instance model not found in MSO CatalogDB: model-version-id=%s",
+ aaiServiceInstance.getModelVersionId());
+ throw new ServiceModelNotFoundException(message);
+ }
+ } else {
+ String message = String.format("Related service instance from AAI not found: service-instance-id=%s",
+ serviceInstanceId);
+ throw new NoServiceInstanceFoundException(message);
+ }
}
- Service service = null;
- if (aaiServiceInstance != null) {
- service = bbInputSetupUtils.getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
- }
- if (aaiServiceInstance != null && service != null) {
- ServiceInstance serviceInstance = this.getExistingServiceInstance(aaiServiceInstance);
- serviceInstance.setModelInfoServiceInstance(this.mapperLayer.mapCatalogServiceIntoServiceInstance(service));
- updateInstanceName(executeBB.getRequestId(), ModelType.service, serviceInstance.getServiceInstanceName());
- gBB = populateGBBWithSIAndAdditionalInfo(requestDetails, serviceInstance, executeBB, requestAction, null);
- } else {
- logger.debug("Related Service Instance from AAI: {}", aaiServiceInstance);
- logger.debug("Related Service Instance Model Info from AAI: {}", service);
- throw new Exception("Could not find relevant information for related Service Instance");
- }
- ServiceInstance serviceInstance = gBB.getServiceInstance();
+
+ ServiceInstance serviceInstance = this.getExistingServiceInstance(aaiServiceInstance);
+ serviceInstance.setModelInfoServiceInstance(this.mapperLayer.mapCatalogServiceIntoServiceInstance(service));
+ updateInstanceName(executeBB.getRequestId(), ModelType.service, serviceInstance.getServiceInstanceName());
+ gBB = populateGBBWithSIAndAdditionalInfo(requestDetails, serviceInstance, executeBB, requestAction, null);
+
+ serviceInstance = gBB.getServiceInstance();
CloudRegion cloudRegion = null;
if (cloudConfiguration == null) {
Optional<CloudRegion> cloudRegionOp = cloudInfoFromAAI.getCloudInfoFromAAI(serviceInstance);
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtils.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtils.java
index fcac86b251..31275f7143 100644
--- a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtils.java
+++ b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtils.java
@@ -587,6 +587,24 @@ public class BBInputSetupUtils {
return aaiRC.exists(l3networkUri);
}
+ public boolean existsAAIVfModuleGloballyByName(String vfModuleName) {
+ AAIResourceUri vfModuleUri =
+ AAIUriFactory.createNodesUri(AAIObjectPlurals.VF_MODULE).queryParam("vf-module-name", vfModuleName);
+ return injectionHelper.getAaiClient().exists(vfModuleUri);
+ }
+
+ public boolean existsAAIConfigurationGloballyByName(String configurationName) {
+ AAIResourceUri configUri = AAIUriFactory.createResourceUri(AAIObjectPlurals.CONFIGURATION)
+ .queryParam("configuration-name", configurationName);
+ return injectionHelper.getAaiClient().exists(configUri);
+ }
+
+ public boolean existsAAIVolumeGroupGloballyByName(String volumeGroupName) {
+ AAIResourceUri volumeGroupUri = AAIUriFactory.createNodesUri(AAIObjectPlurals.VOLUME_GROUP)
+ .queryParam("volume-group-name", volumeGroupName);
+ return injectionHelper.getAaiClient().exists(volumeGroupUri);
+ }
+
public GenericVnfs getAAIVnfsGloballyByName(String vnfName) {
return injectionHelper.getAaiClient()
diff --git a/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundException.java b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundException.java
new file mode 100644
index 0000000000..b9daad6626
--- /dev/null
+++ b/bpmn/MSOCommonBPMN/src/main/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundException.java
@@ -0,0 +1,15 @@
+package org.onap.so.bpmn.servicedecomposition.tasks.exceptions;
+
+public class ServiceModelNotFoundException extends Exception {
+
+ private static final long serialVersionUID = -5551887892983898061L;
+
+ public ServiceModelNotFoundException() {
+ super();
+ }
+
+ public ServiceModelNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupTest.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupTest.java
index 26e4771021..ffbf673cdb 100644
--- a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupTest.java
+++ b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupTest.java
@@ -46,7 +46,9 @@ import java.util.Optional;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
@@ -87,6 +89,8 @@ import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoNetwork;
import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoServiceInstance;
import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoServiceProxy;
import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoVfModule;
+import org.onap.so.bpmn.servicedecomposition.tasks.exceptions.NoServiceInstanceFoundException;
+import org.onap.so.bpmn.servicedecomposition.tasks.exceptions.ServiceModelNotFoundException;
import org.onap.so.client.aai.AAICommonObjectMapperProvider;
import org.onap.so.client.aai.AAIObjectType;
import org.onap.so.client.aai.entities.AAIResultWrapper;
@@ -149,6 +153,9 @@ public class BBInputSetupTest {
@Mock
private RequestsDbClient requestsDbClient;
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
@Before
public void setup() {
SPY_bbInputSetup.setBbInputSetupUtils(SPY_bbInputSetupUtils);
@@ -462,19 +469,50 @@ public class BBInputSetupTest {
assertThat(actual, sameBeanAs(expected));
}
- @Test(expected = Exception.class)
+ @Test
public void testGetGBBALaCarteNonServiceWithoutServiceModelInfo() throws Exception {
ExecuteBuildingBlock executeBB = mapper.readValue(new File(RESOURCE_PATH + "ExecuteBuildingBlockSimple.json"),
ExecuteBuildingBlock.class);
RequestDetails requestDetails = mapper.readValue(
new File(RESOURCE_PATH + "RequestDetailsInput_withRelatedInstanceList.json"), RequestDetails.class);
Map<ResourceKey, String> lookupKeyMap = new HashMap<>();
+ lookupKeyMap.put(ResourceKey.SERVICE_INSTANCE_ID, "si123");
String requestAction = "createInstance";
org.onap.aai.domain.yang.ServiceInstance aaiServiceInstance = new org.onap.aai.domain.yang.ServiceInstance();
aaiServiceInstance.setModelVersionId("modelVersionId");
String resourceId = "123";
String vnfType = "vnfType";
+ doReturn(aaiServiceInstance).when(SPY_bbInputSetupUtils).getAAIServiceInstanceById("si123");
+ doReturn(null).when(SPY_bbInputSetupUtils).getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
+
+ expectedException.expect(ServiceModelNotFoundException.class);
+ expectedException.expectMessage(
+ "Related service instance model not found in MSO CatalogDB: model-version-id=modelVersionId");
+
+ SPY_bbInputSetup.getGBBALaCarteNonService(executeBB, requestDetails, lookupKeyMap, requestAction, resourceId,
+ vnfType);
+ }
+
+ @Test
+ public void testGetGBBALaCarteNonServiceServiceInstanceNotFoundInAAI() throws Exception {
+ ExecuteBuildingBlock executeBB = mapper.readValue(new File(RESOURCE_PATH + "ExecuteBuildingBlockSimple.json"),
+ ExecuteBuildingBlock.class);
+ RequestDetails requestDetails = mapper.readValue(
+ new File(RESOURCE_PATH + "RequestDetailsInput_withRelatedInstanceList.json"), RequestDetails.class);
+ Map<ResourceKey, String> lookupKeyMap = new HashMap<>();
+ lookupKeyMap.put(ResourceKey.SERVICE_INSTANCE_ID, "si123");
+ String requestAction = "createInstance";
+ org.onap.aai.domain.yang.ServiceInstance aaiServiceInstance = new org.onap.aai.domain.yang.ServiceInstance();
+ aaiServiceInstance.setModelVersionId("modelVersionId");
+ String resourceId = "123";
+ String vnfType = "vnfType";
+
+ doReturn(null).when(SPY_bbInputSetupUtils).getAAIServiceInstanceById("si123");
+
+ expectedException.expect(NoServiceInstanceFoundException.class);
+ expectedException.expectMessage("Related service instance from AAI not found: service-instance-id=si123");
+
SPY_bbInputSetup.getGBBALaCarteNonService(executeBB, requestDetails, lookupKeyMap, requestAction, resourceId,
vnfType);
}
@@ -2672,6 +2710,48 @@ public class BBInputSetupTest {
}
@Test
+ public void testGetGBBMacroExistingServiceServiceinstancenotFoundInAai() throws Exception {
+ ExecuteBuildingBlock executeBB = mapper.readValue(new File(RESOURCE_PATH + "ExecuteBuildingBlockSimple.json"),
+ ExecuteBuildingBlock.class);
+ Map<ResourceKey, String> lookupKeyMap = new HashMap<>();
+ lookupKeyMap.put(ResourceKey.SERVICE_INSTANCE_ID, "si123");
+
+ CloudConfiguration cloudConfiguration = new CloudConfiguration();
+ cloudConfiguration.setLcpCloudRegionId("cloudRegionId");
+
+ doReturn(null).when(SPY_bbInputSetupUtils).getAAIServiceInstanceById("si123");
+
+ expectedException.expect(NoServiceInstanceFoundException.class);
+ expectedException.expectMessage("Related service instance from AAI not found: service-instance-id=si123");
+
+ SPY_bbInputSetup.getGBBMacroExistingService(executeBB, lookupKeyMap, "AssignVnfBB", "assign",
+ cloudConfiguration);
+ }
+
+ @Test
+ public void testGetGBBMacroExistingServiceServiceModelNotFound() throws Exception {
+ ExecuteBuildingBlock executeBB = mapper.readValue(new File(RESOURCE_PATH + "ExecuteBuildingBlockSimple.json"),
+ ExecuteBuildingBlock.class);
+ Map<ResourceKey, String> lookupKeyMap = new HashMap<>();
+ lookupKeyMap.put(ResourceKey.SERVICE_INSTANCE_ID, "si123");
+ org.onap.aai.domain.yang.ServiceInstance aaiServiceInstance = new org.onap.aai.domain.yang.ServiceInstance();
+ aaiServiceInstance.setModelVersionId("modelVersionId");
+
+ CloudConfiguration cloudConfiguration = new CloudConfiguration();
+ cloudConfiguration.setLcpCloudRegionId("cloudRegionId");
+
+ doReturn(aaiServiceInstance).when(SPY_bbInputSetupUtils).getAAIServiceInstanceById("si123");
+ doReturn(null).when(SPY_bbInputSetupUtils).getCatalogServiceByModelUUID(aaiServiceInstance.getModelVersionId());
+
+ expectedException.expect(ServiceModelNotFoundException.class);
+ expectedException.expectMessage(
+ "Related service instance model not found in MSO CatalogDB: model-version-id=modelVersionId");
+
+ SPY_bbInputSetup.getGBBMacroExistingService(executeBB, lookupKeyMap, "AssignVnfBB", "assign",
+ cloudConfiguration);
+ }
+
+ @Test
public void testGetVnfId() {
String expected = "vnfId";
ExecuteBuildingBlock executeBB = new ExecuteBuildingBlock();
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtilsTest.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtilsTest.java
index 7780837714..53d167e4af 100644
--- a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtilsTest.java
+++ b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/BBInputSetupUtilsTest.java
@@ -878,4 +878,35 @@ public class BBInputSetupUtilsTest {
assertEquals(actual.get().getConfigurationId(), expected.get().getConfiguration().get(0).getConfigurationId());
}
+ @Test
+ public void existsAAIVfModuleGloballyByNameTest() throws Exception {
+ AAIResourceUri expectedUri =
+ AAIUriFactory.createNodesUri(AAIObjectPlurals.VF_MODULE).queryParam("vf-module-name", "testVfModule");
+ bbInputSetupUtils.existsAAIVfModuleGloballyByName("testVfModule");
+ verify(MOCK_aaiResourcesClient, times(1)).exists(expectedUri);
+ }
+
+ @Test
+ public void existsAAIConfigurationGloballyByNameTest() throws Exception {
+ AAIResourceUri expectedUri = AAIUriFactory.createResourceUri(AAIObjectPlurals.CONFIGURATION)
+ .queryParam("configuration-name", "testConfig");
+ bbInputSetupUtils.existsAAIConfigurationGloballyByName("testConfig");
+ verify(MOCK_aaiResourcesClient, times(1)).exists(expectedUri);
+ }
+
+ @Test
+ public void existsAAINetworksGloballyByNameTest() throws Exception {
+ AAIResourceUri expectedUri =
+ AAIUriFactory.createResourceUri(AAIObjectPlurals.L3_NETWORK).queryParam("network-name", "testNetwork");
+ bbInputSetupUtils.existsAAINetworksGloballyByName("testNetwork");
+ verify(MOCK_aaiResourcesClient, times(1)).exists(expectedUri);
+ }
+
+ @Test
+ public void existsAAIVolumeGroupGloballyByNameTest() throws Exception {
+ AAIResourceUri expectedUri = AAIUriFactory.createNodesUri(AAIObjectPlurals.VOLUME_GROUP)
+ .queryParam("volume-group-name", "testVoumeGroup");
+ bbInputSetupUtils.existsAAIVolumeGroupGloballyByName("testVoumeGroup");
+ verify(MOCK_aaiResourcesClient, times(1)).exists(expectedUri);
+ }
}
diff --git a/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundExceptionTest.java b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundExceptionTest.java
new file mode 100644
index 0000000000..1ab1d7aa9a
--- /dev/null
+++ b/bpmn/MSOCommonBPMN/src/test/java/org/onap/so/bpmn/servicedecomposition/tasks/exceptions/ServiceModelNotFoundExceptionTest.java
@@ -0,0 +1,19 @@
+package org.onap.so.bpmn.servicedecomposition.tasks.exceptions;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class ServiceModelNotFoundExceptionTest {
+
+ @Test
+ public void testRequestValidationException() {
+
+ ServiceModelNotFoundException serviceModelNotFoundException = new ServiceModelNotFoundException();
+ Assert.assertNull(serviceModelNotFoundException.getMessage());
+
+ serviceModelNotFoundException = new ServiceModelNotFoundException("test message");
+ Assert.assertEquals("test message", serviceModelNotFoundException.getMessage());
+
+ }
+}