aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
authorsebdet <sebastien.determe@intl.att.com>2019-04-05 15:15:31 +0200
committersebdet <sebastien.determe@intl.att.com>2019-04-05 15:15:31 +0200
commitdfa86ca8a3d8380487261da22cbf582b547e3276 (patch)
treecff6e438b2d363d25935a3ed743bac97e0314fdd /src/main/java
parent0cb57989949080d6cc3853c432a233605c321388 (diff)
Introduce Camel route
Camel route for Submit operation using http4 component Issue-ID: CLAMP-303 Change-Id: I29804a7db6286dfa84f7eed63813f25299a385e6 Signed-off-by: sebdet <sebastien.determe@intl.att.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/onap/clamp/loop/LoopOperation.java126
-rw-r--r--src/main/java/org/onap/clamp/policy/PolicyOperation.java131
-rw-r--r--src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java38
3 files changed, 100 insertions, 195 deletions
diff --git a/src/main/java/org/onap/clamp/loop/LoopOperation.java b/src/main/java/org/onap/clamp/loop/LoopOperation.java
index 7def783b..5b55ab0d 100644
--- a/src/main/java/org/onap/clamp/loop/LoopOperation.java
+++ b/src/main/java/org/onap/clamp/loop/LoopOperation.java
@@ -45,7 +45,6 @@ import org.onap.clamp.clds.config.ClampProperties;
import org.onap.clamp.clds.util.LoggingUtils;
import org.onap.clamp.clds.util.ONAPLogConstants;
import org.onap.clamp.exception.OperationException;
-import org.onap.clamp.policy.PolicyOperation;
import org.onap.clamp.util.HttpConnectionManager;
import org.slf4j.event.Level;
import org.springframework.beans.factory.annotation.Autowired;
@@ -59,30 +58,30 @@ import org.yaml.snakeyaml.Yaml;
@Component
public class LoopOperation {
- protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class);
- protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger();
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger();
private final DcaeDispatcherServices dcaeDispatcherServices;
private final LoopService loopService;
private LoggingUtils util = new LoggingUtils(logger);
- private PolicyOperation policyOp;
@Autowired
private HttpServletRequest request;
@Autowired
- public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices,
- ClampProperties refProp, HttpConnectionManager httpConnectionManager, PolicyOperation policyOp) {
+ public LoopOperation(LoopService loopService, DcaeDispatcherServices dcaeDispatcherServices,
+ ClampProperties refProp, HttpConnectionManager httpConnectionManager) {
this.loopService = loopService;
this.dcaeDispatcherServices = dcaeDispatcherServices;
- this.policyOp = policyOp;
}
/**
* Deploy the closed loop.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
- * @throws Exceptions during the operation
+ * @throws Exceptions
+ * during the operation
*/
public Loop deployLoop(Exchange camelExchange, String loopName) throws OperationException {
util.entering(request, "CldsService: Deploy model");
@@ -98,10 +97,9 @@ public class LoopOperation {
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.SUBMITTED) {
- String msg = "Deploy loop exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Deploy loop exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be deployed only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
@@ -118,25 +116,27 @@ public class LoopOperation {
Map<String, Object> yamlMap = yaml.load(loop.getBlueprint());
JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject();
- loop.setDcaeDeploymentStatusUrl(dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint));
+ loop.setDcaeDeploymentStatusUrl(
+ dcaeDispatcherServices.createNewDeployment(deploymentId, loop.getDcaeBlueprintId(), bluePrint));
loop.setLastComputedState(LoopState.DEPLOYED);
// save the updated loop
- loopService.saveOrUpdateLoop (loop);
+ loopService.saveOrUpdateLoop(loop);
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
auditLogger.info("Deploy model completed");
util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
+ return loop;
}
/**
* Un deploy closed loop.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
*/
- public Loop unDeployLoop(String loopName) throws OperationException {
+ public Loop unDeployLoop(String loopName) throws OperationException {
util.entering(request, "LoopOperation: Undeploy the closed loop");
Date startTime = new Date();
Loop loop = loopService.getLoop(loopName);
@@ -146,14 +146,13 @@ public class LoopOperation {
util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.toString(), msg, Level.INFO,
ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
- }
+ }
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.DEPLOYED) {
- String msg = "Unploy loop exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Unploy loop exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be undeployed only when it is in DEPLOYED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
@@ -165,7 +164,7 @@ public class LoopOperation {
loop.setLastComputedState(LoopState.SUBMITTED);
// save the updated loop
- loopService.saveOrUpdateLoop (loop);
+ loopService.saveOrUpdateLoop(loop);
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
@@ -175,14 +174,14 @@ public class LoopOperation {
}
private JsonElement wrapSnakeObject(Object o) {
- //NULL => JsonNull
+ // NULL => JsonNull
if (o == null)
return JsonNull.INSTANCE;
// Collection => JsonArray
if (o instanceof Collection) {
JsonArray array = new JsonArray();
- for (Object childObj : (Collection<?>)o)
+ for (Object childObj : (Collection<?>) o)
array.add(wrapSnakeObject(childObj));
return array;
}
@@ -192,14 +191,14 @@ public class LoopOperation {
JsonArray array = new JsonArray();
int length = Array.getLength(array);
- for (int i=0; i<length; i++)
+ for (int i = 0; i < length; i++)
array.add(wrapSnakeObject(Array.get(array, i)));
return array;
}
// Map => JsonObject
if (o instanceof Map) {
- Map<?, ?> map = (Map<?, ?>)o;
+ Map<?, ?> map = (Map<?, ?>) o;
JsonObject jsonObject = new JsonObject();
for (final Map.Entry<?, ?> entry : map.entrySet()) {
@@ -217,12 +216,15 @@ public class LoopOperation {
/**
* Submit the Ms policies.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
- * @throws IOException IO exception
- * @throws Exceptions during the operation
+ * @throws IOException
+ * IO exception
+ * @throws Exceptions
+ * during the operation
*/
- public Loop submitMsPolicies (String loopName) throws OperationException, IOException {
+ public Loop submitMsPolicies(String loopName) throws OperationException, IOException {
util.entering(request, "LoopOperation: delete microservice policies");
Date startTime = new Date();
Loop loop = loopService.getLoop(loopName);
@@ -236,33 +238,34 @@ public class LoopOperation {
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.SUBMITTED && loop.getLastComputedState() != LoopState.DESIGN) {
- String msg = "Submit MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Submit MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
// Establish the api call to Policy to create the ms services
- policyOp.createMsPolicy(loop.getMicroServicePolicies());
+ // policyOp.createMsPolicy(loop.getMicroServicePolicies());
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
auditLogger.info("Deletion of MS policies completed");
util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
+ return loop;
}
-
/**
* Delete the Ms policies.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
- * @throws IOException IO exception
- * @throws Exceptions during the operation
+ * @throws IOException
+ * IO exception
+ * @throws Exceptions
+ * during the operation
*/
- public Loop deleteMsPolicies (Exchange camelExchange, String loopName) throws OperationException, IOException {
+ public Loop deleteMsPolicies(Exchange camelExchange, String loopName) throws OperationException, IOException {
util.entering(request, "LoopOperation: delete microservice policies");
Date startTime = new Date();
Loop loop = loopService.getLoop(loopName);
@@ -276,31 +279,32 @@ public class LoopOperation {
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.SUBMITTED) {
- String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
// Establish the api call to Policy to create the ms services
- policyOp.deleteMsPolicy(loop.getMicroServicePolicies());
+ // policyOp.deleteMsPolicy(loop.getMicroServicePolicies());
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
auditLogger.info("Deletion of MS policies completed");
util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
+ return loop;
}
/**
* Delete the operational policy.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
- * @throws Exceptions during the operation
+ * @throws Exceptions
+ * during the operation
*/
- public Loop deleteOpPolicy (Exchange camelExchange, String loopName) throws OperationException {
+ public Loop deleteOpPolicy(Exchange camelExchange, String loopName) throws OperationException {
util.entering(request, "LoopOperation: delete guard policy");
Date startTime = new Date();
Loop loop = loopService.getLoop(loopName);
@@ -314,31 +318,32 @@ public class LoopOperation {
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.SUBMITTED) {
- String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
// Establish the api call to Policy to delete operational policy
- //client.deleteOpPolicy();
+ // client.deleteOpPolicy();
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
auditLogger.info("Deletion of Guard policy completed");
util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
+ return loop;
}
/**
* Delete the Guard policy.
*
- * @param loopName the loop name
+ * @param loopName
+ * the loop name
* @return the updated loop
- * @throws Exceptions during the operation
+ * @throws Exceptions
+ * during the operation
*/
- public Loop deleteGuardPolicy (Exchange camelExchange, String loopName) throws OperationException {
+ public Loop deleteGuardPolicy(Exchange camelExchange, String loopName) throws OperationException {
util.entering(request, "LoopOperation: delete operational policy");
Date startTime = new Date();
Loop loop = loopService.getLoop(loopName);
@@ -352,20 +357,19 @@ public class LoopOperation {
// verify the current closed loop state
if (loop.getLastComputedState() != LoopState.SUBMITTED) {
- String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ String msg = "Delete MS policies exception: This closed loop is in state:" + loop.getLastComputedState()
+ ". It could be deleted only when it is in SUBMITTED state.";
- util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO,
- ONAPLogConstants.ResponseStatus.ERROR);
+ util.exiting(HttpStatus.CONFLICT.toString(), msg, Level.INFO, ONAPLogConstants.ResponseStatus.ERROR);
throw new OperationException(msg);
}
// Establish the api call to Policy to delete Guard policy
- //client.deleteOpPolicy();
+ // client.deleteOpPolicy();
// audit log
LoggingUtils.setTimeContext(startTime, new Date());
auditLogger.info("Deletion of operational policy completed");
util.exiting(HttpStatus.OK.toString(), "Successful", Level.INFO, ONAPLogConstants.ResponseStatus.COMPLETED);
- return loop;
+ return loop;
}
}
diff --git a/src/main/java/org/onap/clamp/policy/PolicyOperation.java b/src/main/java/org/onap/clamp/policy/PolicyOperation.java
deleted file mode 100644
index edce8ff5..00000000
--- a/src/main/java/org/onap/clamp/policy/PolicyOperation.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
- * reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- *
- */
-
-package org.onap.clamp.policy;
-
-import java.io.IOException;
-import java.util.Set;
-
-import org.onap.clamp.clds.config.ClampProperties;
-import org.onap.clamp.policy.microservice.MicroServicePolicy;
-import org.onap.clamp.util.HttpConnectionManager;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-
-@Component
-public class PolicyOperation {
- protected static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyOperation.class);
- protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
- public static final String POLICY_MSTYPE_PROPERTY_NAME = "policy.ms.type";
- public static final String POLICY_ONAPNAME_PROPERTY_NAME = "policy.onap.name";
- public static final String POLICY_BASENAME_PREFIX_PROPERTY_NAME = "policy.base.policyNamePrefix";
- public static final String POLICY_OP_NAME_PREFIX_PROPERTY_NAME = "policy.op.policyNamePrefix";
- public static final String POLICY_MS_NAME_PREFIX_PROPERTY_NAME = "policy.ms.policyNamePrefix";
- public static final String POLICY_OP_TYPE_PROPERTY_NAME = "policy.op.type";
- public static final String POLICY_GUARD_SUFFIX = "_Guard";
- public static final String POLICY_URL_PROPERTY_NAME = "clamp.config.policy.url";
- public static final String POLICY_URL_SUFFIX = "/versions/1.0.0/policies";
- public static final String POLICY_USER_NAME = "clamp.config.policy.userName";
- public static final String POLICY_PASSWORD = "clamp.config.policy.password";
-
- public static final String TOSCA_DEF_VERSION = "tosca_definitions_version";
- public static final String TOSCA_DEF_VERSION_VALUE = "tosca_simple_yaml_1_0_0";
- public static final String TEMPLATE = "topology_template";
- public static final String POLICIES = "policies";
- public static final String MS_TYPE = "type";
- public static final String MS_VERSION = "version";
- public static final String MS_VERSION_VALUE = "1.0.0";
- public static final String MS_METADATA = "metadata";
- public static final String MS_POLICY_ID = "policy_id";
- public static final String MS_PROPERTIES = "properties";
- public static final String MS_policy = "tca_policy";
-
- private final ClampProperties refProp;
- private final HttpConnectionManager httpConnectionManager;
-
- @Autowired
- public PolicyOperation(ClampProperties refProp, HttpConnectionManager httpConnectionManager) {
- this.refProp = refProp;
- this.httpConnectionManager = httpConnectionManager;
- }
-
- public void createMsPolicy(Set<MicroServicePolicy> policyList) throws IOException {
- // Get policy first? if exist delete???
- // push pdp group
- for (MicroServicePolicy msPolicy:policyList) {
- JsonObject payload = createMsPolicyPayload(msPolicy);
- String policyType = msPolicy.getModelType();
- String url = refProp.getStringValue(POLICY_URL_PROPERTY_NAME) + policyType + POLICY_URL_SUFFIX;
- String userName = refProp.getStringValue(POLICY_USER_NAME);
- String encodedPass = refProp.getStringValue(POLICY_PASSWORD);
- httpConnectionManager.doHttpRequest(url, "POST", payload.toString(), "application/json", "POLICY", userName, encodedPass);
- }
- }
-
- public void deleteMsPolicy(Set<MicroServicePolicy> policyList) throws IOException {
- for (MicroServicePolicy msPolicy:policyList) {
- String policyType = msPolicy.getModelType();
- String url = refProp.getStringValue(POLICY_URL_PROPERTY_NAME) + policyType + POLICY_URL_SUFFIX + "/" + msPolicy.getName();
- String userName = refProp.getStringValue(POLICY_USER_NAME);
- String encodedPass = refProp.getStringValue(POLICY_PASSWORD);
- httpConnectionManager.doHttpRequest(url, "POST", null, null, "POLICY", userName, encodedPass);
- }
- }
-
- private JsonObject createMsPolicyPayload(MicroServicePolicy microService) {
- JsonObject policyConfig = new JsonObject();
- policyConfig.add(MS_policy, microService.getProperties());
-
- JsonObject properties = new JsonObject();
- properties.add(MS_policy, policyConfig);
-
- JsonObject msPolicy = new JsonObject();
- msPolicy.addProperty(MS_TYPE, microService.getModelType());
- msPolicy.addProperty(MS_VERSION, MS_VERSION_VALUE);
- JsonObject metaData = new JsonObject();
- metaData.addProperty(MS_POLICY_ID, microService.getName());
- msPolicy.add(MS_METADATA, metaData);
- msPolicy.add(MS_PROPERTIES, properties);
-
- JsonObject msPolicyWithName = new JsonObject();
- msPolicyWithName.add(microService.getName(), msPolicy);
-
- JsonArray policyArray = new JsonArray();
- policyArray.add(msPolicyWithName);
-
- JsonObject template = new JsonObject();
- template.add(POLICIES, policyArray);
-
- JsonObject configPolicy = new JsonObject();
- configPolicy.addProperty(TOSCA_DEF_VERSION, TOSCA_DEF_VERSION_VALUE);
- configPolicy.add(TEMPLATE, template);
-
- return configPolicy;
- }
-
-}
diff --git a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
index 674bd71d..b6b591db 100644
--- a/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
+++ b/src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
@@ -23,12 +23,18 @@
package org.onap.clamp.policy.operational;
+import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -44,6 +50,7 @@ import org.hibernate.annotations.TypeDefs;
import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
import org.onap.clamp.loop.Loop;
import org.onap.clamp.policy.Policy;
+import org.yaml.snakeyaml.Yaml;
@Entity
@Table(name = "operational_policies")
@@ -156,11 +163,36 @@ public class OperationalPolicy implements Serializable, Policy {
JsonArray policiesArray = new JsonArray();
topologyTemplateNode.add("policies", policiesArray);
- return new GsonBuilder().setPrettyPrinting().create().toJson(policyPayloadResult);
+ JsonObject operationalPolicy = new JsonObject();
+ policiesArray.add(operationalPolicy);
+
+ JsonObject operationalPolicyDetails = new JsonObject();
+ operationalPolicy.add(this.name, operationalPolicyDetails);
+ operationalPolicyDetails.addProperty("type", "onap.policies.controlloop.Operational");
+ operationalPolicyDetails.addProperty("version", "1.0.0");
+
+ JsonObject metadata = new JsonObject();
+ operationalPolicyDetails.add("metadata", metadata);
+ metadata.addProperty("policy-id", this.name);
+
+ operationalPolicyDetails.add("properties", this.configurationsJson.get("operational_policy"));
+
+ Gson gson = new GsonBuilder().create();
+ Map<?, ?> jsonMap = gson.fromJson(gson.toJson(policyPayloadResult), Map.class);
+ return (new Yaml()).dump(jsonMap);
}
- public String createGuardPolicyPayload() {
- return null;
+ public List<String> createGuardPolicyPayloads() {
+ List<String> result = new ArrayList<>();
+
+ JsonObject guard = new JsonObject();
+ JsonElement guardsList = this.getConfigurationsJson().get("guard_policies");
+ for (Entry<String, JsonElement> guardElem : guardsList.getAsJsonObject().entrySet()) {
+ guard.addProperty("policy-id", guardElem.getKey());
+ guard.add("contents", guardElem.getValue());
+ result.add(new GsonBuilder().create().toJson(guard));
+ }
+ return result;
}
}