Adding correct user in aai simulator 89/93089/8
authorwaqas.ikram <waqas.ikram@est.tech>
Thu, 8 Aug 2019 15:57:14 +0000 (15:57 +0000)
committerWaqas Ikram <waqas.ikram@est.tech>
Thu, 8 Aug 2019 15:57:30 +0000 (15:57 +0000)
Plus Fixing belows issues
 - NullpointerException in aai simulator
 - Service Type update in catalogdb
 - OutputRequest format in sdnc simulator

Change-Id: I87c8b814e93cf9bc83b62e90b868c603a15a5560
Issue-ID: SO-1953
Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
plans/so/integration-etsi-testing/config/apply-workarounds.sh
plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProviderImpl.java
plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/resources/application.yaml
plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/BusinessControllerTest.java
plans/so/integration-etsi-testing/so-simulators/common/src/main/java/org/onap/so/simulator/configuration/SimulatorSecurityConfigurer.java
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/controller/OperationsController.java
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/models/Output.java [new file with mode: 0644]
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/models/OutputRequest.java
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/providers/ServiceOperationsCacheServiceProvider.java
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/providers/ServiceOperationsCacheServiceProviderimpl.java
plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/test/java/org/onap/so/sdncsimulator/controller/OperationsControllerTest.java

index 4200a36..21a3aeb 100755 (executable)
@@ -87,6 +87,9 @@ apply_workaround()
  echo "$SCRIPT_NAME $(current_timestamp): Will insert data into $CATALOG_DB"
 mysql -h $DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD $CATALOG_DB << EOF
   BEGIN;
+  
+  UPDATE $NORTH_BOUND_TABLE_NAME SET SERVICE_TYPE="*";
+
   INSERT INTO $BUIDLING_BLOCK_TABLE_NAME (BUILDING_BLOCK_NAME,RESOURCE_TYPE,TARGET_ACTION) values ("EtsiVnfInstantiateBB", "VNF", "ACTIVATE");
   INSERT INTO $BUIDLING_BLOCK_TABLE_NAME (BUILDING_BLOCK_NAME,RESOURCE_TYPE,TARGET_ACTION) values ("EtsiVnfDeleteBB", "VNF", "DEACTIVATE");
  
index 1d12a94..5c022c9 100644 (file)
@@ -101,16 +101,20 @@ public class CustomerCacheServiceProviderImpl extends AbstractCacheServiceProvid
 
             if (serviceSubscription.isPresent()) {
                 LOGGER.info("Found service subscription ...");
-                final List<ServiceInstance> serviceInstancesList = serviceSubscription.get().getServiceInstances()
-                        .getServiceInstance().stream()
-                        .filter(serviceInstance -> serviceInstanceName.equals(serviceInstance.getServiceInstanceName()))
-                        .collect(Collectors.toList());
-                if (serviceInstancesList != null && !serviceInstancesList.isEmpty()) {
-                    LOGGER.info("Found {} service instances ", serviceInstancesList.size());
-                    final ServiceInstances serviceInstances = new ServiceInstances();
-                    serviceInstances.getServiceInstance().addAll(serviceInstancesList);
-                    return Optional.of(serviceInstances);
-
+                final ServiceInstances serviceInstances = serviceSubscription.get().getServiceInstances();
+                if (serviceInstances != null) {
+                    final List<ServiceInstance> serviceInstancesList =
+                            serviceInstances.getServiceInstance().stream()
+                                    .filter(serviceInstance -> serviceInstanceName
+                                            .equals(serviceInstance.getServiceInstanceName()))
+                                    .collect(Collectors.toList());
+                    if (serviceInstancesList != null && !serviceInstancesList.isEmpty()) {
+                        LOGGER.info("Found {} service instances ", serviceInstancesList.size());
+                        final ServiceInstances result = new ServiceInstances();
+                        result.getServiceInstance().addAll(serviceInstancesList);
+                        return Optional.of(result);
+
+                    }
                 }
             }
         }
index 25be8da..de81944 100644 (file)
@@ -13,4 +13,8 @@ spring:
       -  username: aai
          #password: aai.onap.org:demo123456!
          password: $2a$04$crRntT01fAF4kb48mxlvgu68/silcLg.czC1LxQsKTdWuDBPpO3YO
+         role: VID
+      -  username: aai@aai.onap.org
+         #password: demo123456!
+         password: $2a$04$06VCpDvW5ztE7WOvhhvAtOx7JHLghECyZIzOShIbXLWpnshMva8T6
          role: VID
\ No newline at end of file
index ef49716..e7d0785 100644 (file)
@@ -192,7 +192,7 @@ public class BusinessControllerTest {
         invokeHttpPut(url, getServiceInstance());
 
         final String serviceInstanceUrl = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCES_URL
-                + "?service-instance-name=" + SERVICE_NAME;
+                + "?depth=2&service-instance-name=" + SERVICE_NAME;
 
         final ResponseEntity<ServiceInstances> actual = restTemplate.exchange(serviceInstanceUrl, HttpMethod.GET,
                 new HttpEntity<>(getHttpHeaders()), ServiceInstances.class);
@@ -207,6 +207,28 @@ public class BusinessControllerTest {
 
     }
 
+    @Test
+    public void test_getSericeInstance_usingServiceInstanceName_returnRequestErrorIfnoServiceInstanceFound()
+            throws Exception {
+
+
+        final ResponseEntity<Void> response = invokeHttpPut(getCustomerEndPointUrl(), getCustomer());
+
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+
+        final String serviceInstanceUrl = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCES_URL
+                + "?depth=2&service-instance-name=" + SERVICE_NAME;
+
+        final ResponseEntity<RequestError> actual = restTemplate.exchange(serviceInstanceUrl, HttpMethod.GET,
+                new HttpEntity<>(getHttpHeaders()), RequestError.class);
+
+        assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        assertNotNull(actual.getBody().getServiceException());
+
+    }
+
     @Test
     public void test_getSericeInstance_usingServiceInstanceId_ableToRetrieveServiceInstanceFromCache()
             throws Exception {
index d2cf004..5d59cbb 100644 (file)
@@ -21,6 +21,8 @@ package org.onap.so.simulator.configuration;
 
 import java.util.List;
 import org.onap.so.simulator.model.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@@ -33,6 +35,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  *
  */
 public abstract class SimulatorSecurityConfigurer extends WebSecurityConfigurerAdapter {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorSecurityConfigurer.class);
+
 
     private final List<User> users;
 
@@ -51,6 +55,7 @@ public abstract class SimulatorSecurityConfigurer extends WebSecurityConfigurerA
                 auth.inMemoryAuthentication().passwordEncoder(passwordEncoder());
         for (int index = 0; index < users.size(); index++) {
             final User user = users.get(index);
+            LOGGER.info("Adding {} to InMemoryUserDetailsManager ...", user);
             inMemoryAuthentication.withUser(user.getUsername()).password(user.getPassword()).roles(user.getRole());
             if (index < users.size()) {
                 inMemoryAuthentication.and();
index 03fbe7e..0074029 100644 (file)
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.MediaType;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServiceOperationInformation;
 import org.onap.so.sdncsimulator.models.InputRequest;
+import org.onap.so.sdncsimulator.models.Output;
 import org.onap.so.sdncsimulator.models.OutputRequest;
 import org.onap.so.sdncsimulator.providers.ServiceOperationsCacheServiceProvider;
 import org.slf4j.Logger;
@@ -66,10 +67,10 @@ public class OperationsController {
             return ResponseEntity.badRequest().build();
         }
 
-        final OutputRequest outputRequest =
-                cacheServiceProvider.putServiceOperationInformation(apiServiceOperationInformation);
+        final Output output = cacheServiceProvider.putServiceOperationInformation(apiServiceOperationInformation);
+        final OutputRequest outputRequest = new OutputRequest(output);
 
-        if (outputRequest.getResponseCode().equals(HttpStatus.OK.toString())) {
+        if (output.getResponseCode().equals(HttpStatus.OK.toString())) {
             return ResponseEntity.ok(outputRequest);
         }
 
diff --git a/plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/models/Output.java b/plans/so/integration-etsi-testing/so-simulators/sdnc-simulator/src/main/java/org/onap/so/sdncsimulator/models/Output.java
new file mode 100644 (file)
index 0000000..554989d
--- /dev/null
@@ -0,0 +1,153 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.sdncsimulator.models;
+
+import org.onap.sdnc.northbound.client.model.GenericResourceApiInstanceReference;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class Output {
+
+    @JsonProperty("response-message")
+    private String responseMessage;
+
+    @JsonProperty("ack-final-indicator")
+    private String ackFinalIndicator;
+
+    @JsonProperty("svc-request-id")
+    private String svcRequestId;
+
+    @JsonProperty("response-code")
+    private String responseCode;
+
+    @JsonProperty("service-response-information")
+    private GenericResourceApiInstanceReference serviceResponseInformation = null;
+
+    /**
+     * @return the responseMessage
+     */
+    public String getResponseMessage() {
+        return responseMessage;
+    }
+
+    /**
+     * @param responseMessage the responseMessage to set
+     */
+    public void setResponseMessage(final String responseMessage) {
+        this.responseMessage = responseMessage;
+    }
+
+    /**
+     * @return the ackFinalIndicator
+     */
+    public String getAckFinalIndicator() {
+        return ackFinalIndicator;
+    }
+
+    /**
+     * @param ackFinalIndicator the ackFinalIndicator to set
+     */
+    public void setAckFinalIndicator(final String ackFinalIndicator) {
+        this.ackFinalIndicator = ackFinalIndicator;
+    }
+
+    /**
+     * @return the svcRequestId
+     */
+    public String getSvcRequestId() {
+        return svcRequestId;
+    }
+
+    /**
+     * @param svcRequestId the svcRequestId to set
+     */
+    public void setSvcRequestId(final String svcRequestId) {
+        this.svcRequestId = svcRequestId;
+    }
+
+    /**
+     * @return the responseCode
+     */
+    public String getResponseCode() {
+        return responseCode;
+    }
+
+    /**
+     * @param responseCode the responseCode to set
+     */
+    public void setResponseCode(final String responseCode) {
+        this.responseCode = responseCode;
+    }
+
+    /**
+     * @return the serviceResponseInformation
+     */
+    public GenericResourceApiInstanceReference getServiceResponseInformation() {
+        return serviceResponseInformation;
+    }
+
+    /**
+     * @param serviceResponseInformation the serviceResponseInformation to set
+     */
+    public void setServiceResponseInformation(final GenericResourceApiInstanceReference serviceResponseInformation) {
+        this.serviceResponseInformation = serviceResponseInformation;
+    }
+
+    public Output responseMessage(final String responseMessage) {
+        this.responseMessage = responseMessage;
+        return this;
+    }
+
+    public Output ackFinalIndicator(final String ackFinalIndicator) {
+        this.ackFinalIndicator = ackFinalIndicator;
+        return this;
+    }
+
+    public Output svcRequestId(final String svcRequestId) {
+        this.svcRequestId = svcRequestId;
+        return this;
+    }
+
+    public Output responseCode(final String responseCode) {
+        this.responseCode = responseCode;
+        return this;
+    }
+
+    public Output serviceResponseInformation(final GenericResourceApiInstanceReference serviceResponseInformation) {
+        this.serviceResponseInformation = serviceResponseInformation;
+        return this;
+    }
+
+
+    @JsonIgnore
+    @Override
+    public String toString() {
+        return "OutputRequest [responseMessage=" + responseMessage + ", ackFinalIndicator=" + ackFinalIndicator
+                + ", svcRequestId=" + svcRequestId + ", responseCode=" + responseCode + ", serviceResponseInformation="
+                + serviceResponseInformation + "]";
+    }
+
+
+
+}
index 7539523..97d2056 100644 (file)
  */
 package org.onap.so.sdncsimulator.models;
 
-import org.onap.sdnc.northbound.client.model.GenericResourceApiInstanceReference;
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonRootName;
 
 /**
  * @author Waqas Ikram (waqas.ikram@est.tech)
  *
  */
-@JsonRootName("output")
-public class OutputRequest {
-
-    @JsonProperty("response-message")
-    private String responseMessage;
-
-    @JsonProperty("ack-final-indicator")
-    private String ackFinalIndicator;
-
-    @JsonProperty("svc-request-id")
-    private String svcRequestId;
-
-    @JsonProperty("response-code")
-    private String responseCode;
-
-    @JsonProperty("service-response-information")
-    private GenericResourceApiInstanceReference serviceResponseInformation = null;
-
-    /**
-     * @return the responseMessage
-     */
-    public String getResponseMessage() {
-        return responseMessage;
-    }
-
-    /**
-     * @param responseMessage the responseMessage to set
-     */
-    public void setResponseMessage(final String responseMessage) {
-        this.responseMessage = responseMessage;
-    }
-
-    /**
-     * @return the ackFinalIndicator
-     */
-    public String getAckFinalIndicator() {
-        return ackFinalIndicator;
-    }
-
-    /**
-     * @param ackFinalIndicator the ackFinalIndicator to set
-     */
-    public void setAckFinalIndicator(final String ackFinalIndicator) {
-        this.ackFinalIndicator = ackFinalIndicator;
-    }
-
-    /**
-     * @return the svcRequestId
-     */
-    public String getSvcRequestId() {
-        return svcRequestId;
-    }
-
-    /**
-     * @param svcRequestId the svcRequestId to set
-     */
-    public void setSvcRequestId(final String svcRequestId) {
-        this.svcRequestId = svcRequestId;
-    }
-
-    /**
-     * @return the responseCode
-     */
-    public String getResponseCode() {
-        return responseCode;
-    }
-
-    /**
-     * @param responseCode the responseCode to set
-     */
-    public void setResponseCode(final String responseCode) {
-        this.responseCode = responseCode;
-    }
 
-    /**
-     * @return the serviceResponseInformation
-     */
-    public GenericResourceApiInstanceReference getServiceResponseInformation() {
-        return serviceResponseInformation;
-    }
+public class OutputRequest {
+    @JsonProperty("output")
+    private Output output;
 
-    /**
-     * @param serviceResponseInformation the serviceResponseInformation to set
-     */
-    public void setServiceResponseInformation(final GenericResourceApiInstanceReference serviceResponseInformation) {
-        this.serviceResponseInformation = serviceResponseInformation;
-    }
+    public OutputRequest() {}
 
-    public OutputRequest responseMessage(final String responseMessage) {
-        this.responseMessage = responseMessage;
-        return this;
+    public OutputRequest(final Output output) {
+        this.output = output;
     }
 
-    public OutputRequest ackFinalIndicator(final String ackFinalIndicator) {
-        this.ackFinalIndicator = ackFinalIndicator;
-        return this;
-    }
 
-    public OutputRequest svcRequestId(final String svcRequestId) {
-        this.svcRequestId = svcRequestId;
-        return this;
+    public Output getOutput() {
+        return output;
     }
 
-    public OutputRequest responseCode(final String responseCode) {
-        this.responseCode = responseCode;
-        return this;
+    public void setOutput(final Output output) {
+        this.output = output;
     }
 
-    public OutputRequest serviceResponseInformation(
-            final GenericResourceApiInstanceReference serviceResponseInformation) {
-        this.serviceResponseInformation = serviceResponseInformation;
-        return this;
-    }
-
-
-    @JsonIgnore
     @Override
     public String toString() {
-        return "OutputRequest [responseMessage=" + responseMessage + ", ackFinalIndicator=" + ackFinalIndicator
-                + ", svcRequestId=" + svcRequestId + ", responseCode=" + responseCode + ", serviceResponseInformation="
-                + serviceResponseInformation + "]";
+        return "OutputRequest [output=" + output + "]";
     }
 
-
 }
index 5194d49..a0116c4 100644 (file)
@@ -22,7 +22,7 @@ package org.onap.so.sdncsimulator.providers;
 import java.util.Optional;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServiceModelInfrastructure;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServiceOperationInformation;
-import org.onap.so.sdncsimulator.models.OutputRequest;
+import org.onap.so.sdncsimulator.models.Output;
 
 /**
  * @author Waqas Ikram (waqas.ikram@est.tech)
@@ -30,7 +30,7 @@ import org.onap.so.sdncsimulator.models.OutputRequest;
  */
 public interface ServiceOperationsCacheServiceProvider {
 
-    OutputRequest putServiceOperationInformation(
+    Output putServiceOperationInformation(
             final GenericResourceApiServiceOperationInformation apiServiceOperationInformation);
 
     Optional<GenericResourceApiServiceModelInfrastructure> getGenericResourceApiServiceModelInfrastructure(
index 37773e1..620742a 100644 (file)
@@ -46,7 +46,7 @@ import org.onap.sdnc.northbound.client.model.GenericResourceApiServicemodelinfra
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServicestatusServiceStatus;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServicetopologyServiceTopology;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiServicetopologyidentifierServiceTopologyIdentifier;
-import org.onap.so.sdncsimulator.models.OutputRequest;
+import org.onap.so.sdncsimulator.models.Output;
 import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -73,7 +73,7 @@ public class ServiceOperationsCacheServiceProviderimpl extends AbstractCacheServ
     }
 
     @Override
-    public OutputRequest putServiceOperationInformation(final GenericResourceApiServiceOperationInformation input) {
+    public Output putServiceOperationInformation(final GenericResourceApiServiceOperationInformation input) {
 
         final GenericResourceApiSdncrequestheaderSdncRequestHeader requestHeader = input.getSdncRequestHeader();
         final String svcRequestId = requestHeader != null ? requestHeader.getSvcRequestId() : null;
@@ -94,13 +94,13 @@ public class ServiceOperationsCacheServiceProviderimpl extends AbstractCacheServ
 
             final GenericResourceApiServicestatusServiceStatus serviceStatus = service.getServiceStatus();
 
-            return new OutputRequest().ackFinalIndicator(serviceStatus.getFinalIndicator())
+            return new Output().ackFinalIndicator(serviceStatus.getFinalIndicator())
                     .responseCode(serviceStatus.getResponseCode()).responseMessage(serviceStatus.getResponseMessage())
                     .svcRequestId(svcRequestId).serviceResponseInformation(new GenericResourceApiInstanceReference()
                             .instanceId(serviceInstanceId).objectPath(RESTCONF_CONFIG_END_POINT + serviceInstanceId));
 
         }
-        return new OutputRequest().ackFinalIndicator(YES).responseCode(HttpStatus.BAD_REQUEST.toString())
+        return new Output().ackFinalIndicator(YES).responseCode(HttpStatus.BAD_REQUEST.toString())
                 .responseMessage("Service instance not found").svcRequestId(svcRequestId);
     }
 
index bcfff95..af46ab4 100644 (file)
@@ -32,6 +32,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.onap.sdnc.northbound.client.model.GenericResourceApiInstanceReference;
 import org.onap.so.sdncsimulator.models.InputRequest;
+import org.onap.so.sdncsimulator.models.Output;
 import org.onap.so.sdncsimulator.models.OutputRequest;
 import org.onap.so.sdncsimulator.providers.ServiceOperationsCacheServiceProvider;
 import org.onap.so.sdncsimulator.utils.Constants;
@@ -92,9 +93,13 @@ public class OperationsControllerTest {
 
         assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
         assertTrue(responseEntity.hasBody());
-        final OutputRequest actualObject = responseEntity.getBody();
-        assertNotNull(actualObject);
 
+        final OutputRequest actualOutputRequest = responseEntity.getBody();
+        assertNotNull(actualOutputRequest);
+
+        final Output actualObject = actualOutputRequest.getOutput();
+
+        assertNotNull(actualObject);
         assertEquals(HttpStatus.OK.toString(), actualObject.getResponseCode());
         assertEquals(Constants.YES, actualObject.getAckFinalIndicator());
         assertEquals(SVC_REQUEST_ID, actualObject.getSvcRequestId());
@@ -126,8 +131,12 @@ public class OperationsControllerTest {
 
         assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
         assertTrue(responseEntity.hasBody());
-        final OutputRequest actualObject = responseEntity.getBody();
 
+        final OutputRequest actualOutputRequest = responseEntity.getBody();
+        assertNotNull(actualOutputRequest);
+
+        final Output actualObject = actualOutputRequest.getOutput();
+        assertNotNull(actualObject);
         assertEquals(HttpStatus.BAD_REQUEST.toString(), actualObject.getResponseCode());
         assertEquals(SVC_REQUEST_ID, actualObject.getSvcRequestId());
         assertEquals(Constants.YES, actualObject.getAckFinalIndicator());
@@ -138,7 +147,6 @@ public class OperationsControllerTest {
         return getHttpHeaders(userCredentials.getUsers().iterator().next().getUsername());
     }
 
-
     private String getUrl() {
         return "http://localhost:" + port + Constants.OPERATIONS_URL + SERVICE_TOPOLOGY_OPERATION_URL;
     }