Refactor the java packages
[clamp.git] / src / main / java / org / onap / clamp / clds / client / req / sdc / SdcCatalogServices.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP CLAMP\r
4  * ================================================================================\r
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights\r
6  *                             reserved.\r
7  * ================================================================================\r
8  * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * you may not use this file except in compliance with the License.\r
10  * You may obtain a copy of the License at\r
11  *\r
12  * http://www.apache.org/licenses/LICENSE-2.0\r
13  *\r
14  * Unless required by applicable law or agreed to in writing, software\r
15  * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * See the License for the specific language governing permissions and\r
18  * limitations under the License.\r
19  * ============LICENSE_END============================================\r
20  * ===================================================================\r
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  */\r
23 \r
24 package org.onap.clamp.clds.client.req.sdc;\r
25 \r
26 import com.att.eelf.configuration.EELFLogger;\r
27 import com.att.eelf.configuration.EELFManager;\r
28 import com.fasterxml.jackson.databind.JsonNode;\r
29 import com.fasterxml.jackson.databind.ObjectMapper;\r
30 import com.fasterxml.jackson.databind.node.ArrayNode;\r
31 import com.fasterxml.jackson.databind.node.ObjectNode;\r
32 import com.fasterxml.jackson.databind.node.TextNode;\r
33 \r
34 import java.io.BufferedReader;\r
35 import java.io.DataOutputStream;\r
36 import java.io.IOException;\r
37 import java.io.InputStream;\r
38 import java.io.InputStreamReader;\r
39 import java.io.Reader;\r
40 import java.io.StringReader;\r
41 import java.net.HttpURLConnection;\r
42 import java.net.URL;\r
43 import java.nio.charset.StandardCharsets;\r
44 import java.security.GeneralSecurityException;\r
45 import java.util.ArrayList;\r
46 import java.util.Base64;\r
47 import java.util.Collections;\r
48 import java.util.Date;\r
49 import java.util.Iterator;\r
50 import java.util.List;\r
51 \r
52 import javax.ws.rs.BadRequestException;\r
53 \r
54 import org.apache.commons.codec.DecoderException;\r
55 import org.apache.commons.codec.digest.DigestUtils;\r
56 import org.apache.commons.csv.CSVFormat;\r
57 import org.apache.commons.csv.CSVRecord;\r
58 import org.apache.commons.io.IOUtils;\r
59 import org.apache.commons.lang3.StringUtils;\r
60 import org.apache.http.HttpHeaders;\r
61 import org.onap.clamp.clds.exception.SdcCommunicationException;\r
62 import org.onap.clamp.clds.model.CldsAlarmCondition;\r
63 import org.onap.clamp.clds.model.CldsDBServiceCache;\r
64 import org.onap.clamp.clds.model.CldsSdcArtifact;\r
65 import org.onap.clamp.clds.model.CldsSdcResource;\r
66 import org.onap.clamp.clds.model.CldsSdcResourceBasicInfo;\r
67 import org.onap.clamp.clds.model.CldsSdcServiceDetail;\r
68 import org.onap.clamp.clds.model.CldsSdcServiceInfo;\r
69 import org.onap.clamp.clds.model.CldsServiceData;\r
70 import org.onap.clamp.clds.model.CldsVfData;\r
71 import org.onap.clamp.clds.model.CldsVfKPIData;\r
72 import org.onap.clamp.clds.model.CldsVfcData;\r
73 import org.onap.clamp.clds.model.prop.Global;\r
74 import org.onap.clamp.clds.model.prop.ModelProperties;\r
75 import org.onap.clamp.clds.model.refprop.RefProp;\r
76 import org.onap.clamp.clds.util.CryptoUtils;\r
77 import org.onap.clamp.clds.util.LoggingUtils;\r
78 import org.springframework.beans.factory.annotation.Autowired;\r
79 \r
80 public class SdcCatalogServices {\r
81     protected static final EELFLogger logger                        = EELFManager.getInstance()\r
82             .getLogger(SdcCatalogServices.class);\r
83     protected static final EELFLogger metricsLogger                 = EELFManager.getInstance().getMetricsLogger();\r
84     private static final String       RESOURCE_VF_TYPE              = "VF";\r
85     private static final String       RESOURCE_VFC_TYPE             = "VFC";\r
86     private static final String       RESOURCE_CVFC_TYPE            = "CVFC";\r
87     public static final String        SDC_REQUESTID_PROPERTY_NAME   = "sdc.header.requestId";\r
88     private static final String       SDC_METADATA_URL_PREFIX       = "/metadata";\r
89     private static final String       SDC_INSTANCE_ID_PROPERTY_NAME = "sdc.InstanceID";\r
90     private static final String       SDC_CATALOG_URL_PROPERTY_NAME = "sdc.catalog.url";\r
91     private static final String       SDC_SERVICE_URL_PROPERTY_NAME = "sdc.serviceUrl";\r
92     private static final String       SDC_INSTANCE_ID_CLAMP         = "CLAMP-Tool";\r
93     private static final String       RESOURCE_URL_PREFIX           = "resources";\r
94     @Autowired\r
95     private RefProp                   refProp;\r
96     protected CryptoUtils             cryptoUtils                   = new CryptoUtils();\r
97 \r
98     /**\r
99      * Return SDC id and pw as a HTTP Basic Auth string (for example: Basic\r
100      * dGVzdDoxMjM0NTY=).\r
101      *\r
102      * @return The String with Basic Auth and password\r
103      * @throws GeneralSecurityException\r
104      *             In case of issue when decryting the SDC password\r
105      * @throws DecoderException\r
106      *             In case of issues with the decoding of the HexString message\r
107      */\r
108     private String getSdcBasicAuth() throws GeneralSecurityException, DecoderException {\r
109         String sdcId = refProp.getStringValue("sdc.serviceUsername");\r
110         String sdcPw = refProp.getStringValue("sdc.servicePassword");\r
111         String password = cryptoUtils.decrypt(sdcPw);\r
112         String idPw = Base64.getEncoder().encodeToString((sdcId + ":" + password).getBytes(StandardCharsets.UTF_8));\r
113         return "Basic " + idPw;\r
114     }\r
115 \r
116     /**\r
117      * This method get the SDC services Information with the corresponding\r
118      * Service UUID.\r
119      * \r
120      * @param uuid\r
121      *            The service UUID\r
122      * @return A Json String with all the service list\r
123      * @throws GeneralSecurityException\r
124      *             In case of issue when decryting the SDC password\r
125      * @throws DecoderException\r
126      *             In case of issues with the decoding of the Hex String\r
127      */\r
128     public String getSdcServicesInformation(String uuid) throws GeneralSecurityException, DecoderException {\r
129         Date startTime = new Date();\r
130         String baseUrl = refProp.getStringValue(SDC_SERVICE_URL_PROPERTY_NAME);\r
131         String basicAuth = getSdcBasicAuth();\r
132         LoggingUtils.setTargetContext("SDC", "getSdcServicesInformation");\r
133         try {\r
134             String url = baseUrl;\r
135             if (uuid != null) {\r
136                 url = baseUrl + "/" + uuid + SDC_METADATA_URL_PREFIX;\r
137             }\r
138             URL urlObj = new URL(url);\r
139             HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();\r
140             conn.setRequestProperty(refProp.getStringValue(SDC_INSTANCE_ID_PROPERTY_NAME), SDC_INSTANCE_ID_CLAMP);\r
141             conn.setRequestProperty(HttpHeaders.AUTHORIZATION, basicAuth);\r
142             conn.setRequestProperty(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");\r
143             conn.setRequestProperty(refProp.getStringValue(SDC_REQUESTID_PROPERTY_NAME), LoggingUtils.getRequestId());\r
144             conn.setRequestMethod("GET");\r
145             String resp = getResponse(conn);\r
146             logger.info(resp);\r
147             // metrics log\r
148             LoggingUtils.setResponseContext("0", "Get sdc services success", this.getClass().getName());\r
149             return resp;\r
150         } catch (IOException e) {\r
151             LoggingUtils.setResponseContext("900", "Get sdc services failed", this.getClass().getName());\r
152             LoggingUtils.setErrorContext("900", "Get sdc services error");\r
153             logger.error("not able to get any service information from sdc for uuid:" + uuid, e);\r
154         } finally {\r
155             LoggingUtils.setTimeContext(startTime, new Date());\r
156             metricsLogger.info("getSdcServicesInformation complete");\r
157         }\r
158         return "";\r
159     }\r
160 \r
161     /**\r
162      * To remove duplicate serviceUUIDs from sdc services List.\r
163      * \r
164      * @param rawCldsSdcServiceList\r
165      *            A list of CldsSdcServiceInfo\r
166      * @return A list of CldsSdcServiceInfo without duplicate service UUID\r
167      */\r
168     public List<CldsSdcServiceInfo> removeDuplicateServices(List<CldsSdcServiceInfo> rawCldsSdcServiceList) {\r
169         List<CldsSdcServiceInfo> cldsSdcServiceInfoList = null;\r
170         if (rawCldsSdcServiceList != null && !rawCldsSdcServiceList.isEmpty()) {\r
171             // sort list\r
172             Collections.sort(rawCldsSdcServiceList);\r
173             // and then take only the services with the max version (last in the\r
174             // list with the same name)\r
175             cldsSdcServiceInfoList = new ArrayList<>();\r
176             for (int i = 1; i < rawCldsSdcServiceList.size(); i++) {\r
177                 // compare name with previous - if not equal, then keep the\r
178                 // previous (it's the last with that name)\r
179                 CldsSdcServiceInfo prev = rawCldsSdcServiceList.get(i - 1);\r
180                 if (!rawCldsSdcServiceList.get(i).getName().equals(prev.getName())) {\r
181                     cldsSdcServiceInfoList.add(prev);\r
182                 }\r
183             }\r
184             // add the last in the list\r
185             cldsSdcServiceInfoList.add(rawCldsSdcServiceList.get(rawCldsSdcServiceList.size() - 1));\r
186         }\r
187         return cldsSdcServiceInfoList;\r
188     }\r
189 \r
190     /**\r
191      * To remove duplicate serviceUUIDs from sdc resources List.\r
192      * \r
193      * @param rawCldsSdcResourceList\r
194      * @return\r
195      */\r
196     public List<CldsSdcResource> removeDuplicateSdcResourceInstances(List<CldsSdcResource> rawCldsSdcResourceList) {\r
197         List<CldsSdcResource> cldsSdcResourceList = null;\r
198         if (rawCldsSdcResourceList != null && !rawCldsSdcResourceList.isEmpty()) {\r
199             // sort list\r
200             Collections.sort(rawCldsSdcResourceList);\r
201             // and then take only the resources with the max version (last in\r
202             // the list with the same name)\r
203             cldsSdcResourceList = new ArrayList<>();\r
204             for (int i = 1; i < rawCldsSdcResourceList.size(); i++) {\r
205                 // compare name with previous - if not equal, then keep the\r
206                 // previous (it's the last with that name)\r
207                 CldsSdcResource prev = rawCldsSdcResourceList.get(i - 1);\r
208                 if (!rawCldsSdcResourceList.get(i).getResourceInstanceName().equals(prev.getResourceInstanceName())) {\r
209                     cldsSdcResourceList.add(prev);\r
210                 }\r
211             }\r
212             // add the last in the list\r
213             cldsSdcResourceList.add(rawCldsSdcResourceList.get(rawCldsSdcResourceList.size() - 1));\r
214         }\r
215         return cldsSdcResourceList;\r
216     }\r
217 \r
218     /**\r
219      * To remove duplicate basic resources with same resourceUUIDs.\r
220      * \r
221      * @param rawCldsSdcResourceListBasicList\r
222      * @return\r
223      */\r
224     public List<CldsSdcResourceBasicInfo> removeDuplicateSdcResourceBasicInfo(\r
225             List<CldsSdcResourceBasicInfo> rawCldsSdcResourceListBasicList) {\r
226         List<CldsSdcResourceBasicInfo> cldsSdcResourceBasicInfoList = null;\r
227         if (rawCldsSdcResourceListBasicList != null && !rawCldsSdcResourceListBasicList.isEmpty()) {\r
228             // sort list\r
229             Collections.sort(rawCldsSdcResourceListBasicList);\r
230             // and then take only the resources with the max version (last in\r
231             // the list with the same name)\r
232             cldsSdcResourceBasicInfoList = new ArrayList<>();\r
233             for (int i = 1; i < rawCldsSdcResourceListBasicList.size(); i++) {\r
234                 // compare name with previous - if not equal, then keep the\r
235                 // previous (it's the last with that name)\r
236                 CldsSdcResourceBasicInfo prev = rawCldsSdcResourceListBasicList.get(i - 1);\r
237                 if (!rawCldsSdcResourceListBasicList.get(i).getName().equals(prev.getName())) {\r
238                     cldsSdcResourceBasicInfoList.add(prev);\r
239                 }\r
240             }\r
241             // add the last in the list\r
242             cldsSdcResourceBasicInfoList\r
243                     .add(rawCldsSdcResourceListBasicList.get(rawCldsSdcResourceListBasicList.size() - 1));\r
244         }\r
245         return cldsSdcResourceBasicInfoList;\r
246     }\r
247 \r
248     /**\r
249      * To get ServiceUUID by using serviceInvariantUUID.\r
250      * \r
251      * @param invariantId\r
252      *            The invariant ID\r
253      * @return The service UUID\r
254      * @throws GeneralSecurityException\r
255      *             In case of issue when decryting the SDC password\r
256      * @throws DecoderException\r
257      *             In case of issues with the decoding of the Hex String\r
258      */\r
259     public String getServiceUuidFromServiceInvariantId(String invariantId)\r
260             throws GeneralSecurityException, DecoderException {\r
261         String serviceUuid = "";\r
262         String responseStr = getSdcServicesInformation(null);\r
263         List<CldsSdcServiceInfo> rawCldsSdcServicesList = getCldsSdcServicesListFromJson(responseStr);\r
264         List<CldsSdcServiceInfo> cldsSdcServicesList = removeDuplicateServices(rawCldsSdcServicesList);\r
265         if (cldsSdcServicesList != null && !cldsSdcServicesList.isEmpty()) {\r
266             for (CldsSdcServiceInfo currCldsSdcServiceInfo : cldsSdcServicesList) {\r
267                 if (currCldsSdcServiceInfo != null && currCldsSdcServiceInfo.getInvariantUUID() != null\r
268                         && currCldsSdcServiceInfo.getInvariantUUID().equalsIgnoreCase(invariantId)) {\r
269                     serviceUuid = currCldsSdcServiceInfo.getUuid();\r
270                     break;\r
271                 }\r
272             }\r
273         }\r
274         return serviceUuid;\r
275     }\r
276 \r
277     /**\r
278      * To get CldsAsdsServiceInfo class by parsing json string.\r
279      * \r
280      * @param jsonStr\r
281      *            The Json string that must be decoded\r
282      * @return The list of CldsSdcServiceInfo, if there is a failure it return\r
283      *         an empty list\r
284      */\r
285     public List<CldsSdcServiceInfo> getCldsSdcServicesListFromJson(String jsonStr) {\r
286         ObjectMapper objectMapper = new ObjectMapper();\r
287         if (StringUtils.isBlank(jsonStr)) {\r
288             return new ArrayList<>();\r
289         }\r
290         try {\r
291             return objectMapper.readValue(jsonStr,\r
292                     objectMapper.getTypeFactory().constructCollectionType(List.class, CldsSdcServiceInfo.class));\r
293         } catch (IOException e) {\r
294             logger.error("Error when attempting to decode the JSON containing CldsSdcServiceInfo", e);\r
295             return new ArrayList<>();\r
296         }\r
297     }\r
298 \r
299     /**\r
300      * To get List of CldsSdcResourceBasicInfo class by parsing json string.\r
301      *\r
302      * @param jsonStr\r
303      *            The JSOn string that must be decoded\r
304      * @return The list of CldsSdcResourceBasicInfo, an empty list in case of\r
305      *         issues\r
306      */\r
307     public List<CldsSdcResourceBasicInfo> getAllSdcResourcesListFromJson(String jsonStr) {\r
308         ObjectMapper objectMapper = new ObjectMapper();\r
309         if (StringUtils.isBlank(jsonStr)) {\r
310             return new ArrayList<>();\r
311         }\r
312         try {\r
313             return objectMapper.readValue(jsonStr,\r
314                     objectMapper.getTypeFactory().constructCollectionType(List.class, CldsSdcResourceBasicInfo.class));\r
315         } catch (IOException e) {\r
316             logger.error("Exception occurred when attempting to decode the list of CldsSdcResourceBasicInfo JSON", e);\r
317             return new ArrayList<>();\r
318         }\r
319     }\r
320 \r
321     /**\r
322      * To get CldsAsdsResource class by parsing json string.\r
323      * \r
324      * @param jsonStr\r
325      * @return\r
326      * @throws IOException\r
327      */\r
328     public CldsSdcResource getCldsSdcResourceFromJson(String jsonStr) throws IOException {\r
329         ObjectMapper objectMapper = new ObjectMapper();\r
330         return objectMapper.readValue(jsonStr, CldsSdcResource.class);\r
331     }\r
332 \r
333     /**\r
334      * To get CldsSdcServiceDetail by parsing json string.\r
335      * \r
336      * @param jsonStr\r
337      * @return\r
338      */\r
339     public CldsSdcServiceDetail getCldsSdcServiceDetailFromJson(String jsonStr) {\r
340         ObjectMapper objectMapper = new ObjectMapper();\r
341         try {\r
342             return objectMapper.readValue(jsonStr, CldsSdcServiceDetail.class);\r
343         } catch (IOException e) {\r
344             logger.error("Exception when attempting to decode the CldsSdcServiceDetail JSON", e);\r
345             return null;\r
346         }\r
347     }\r
348 \r
349     /**\r
350      * To upload artifact to sdc based on serviceUUID and resource name on url.\r
351      * \r
352      * @param prop\r
353      * @param userid\r
354      * @param url\r
355      * @param formattedSdcReq\r
356      * @return\r
357      * @throws GeneralSecurityException\r
358      */\r
359     public String uploadArtifactToSdc(ModelProperties prop, String userid, String url, String formattedSdcReq)\r
360             throws GeneralSecurityException {\r
361         // Verify whether it is triggered by Validation Test button from UI\r
362         if (prop.isTestOnly()) {\r
363             return "sdc artifact upload not executed for test action";\r
364         }\r
365         try {\r
366             logger.info("userid=" + userid);\r
367             byte[] postData = formattedSdcReq.getBytes(StandardCharsets.UTF_8);\r
368             int postDataLength = postData.length;\r
369             HttpURLConnection conn = getSdcHttpUrlConnection(userid, postDataLength, url, formattedSdcReq);\r
370             try (DataOutputStream wr = new DataOutputStream(conn.getOutputStream())) {\r
371                 wr.write(postData);\r
372             }\r
373             boolean requestFailed = true;\r
374             int responseCode = conn.getResponseCode();\r
375             logger.info("responseCode=" + responseCode);\r
376             if (responseCode == 200) {\r
377                 requestFailed = false;\r
378             }\r
379             String responseStr = getResponse(conn);\r
380             if (responseStr != null && requestFailed) {\r
381                 logger.error("requestFailed - responseStr=" + responseStr);\r
382                 throw new BadRequestException(responseStr);\r
383             }\r
384             return responseStr;\r
385         } catch (IOException e) {\r
386             logger.error("Exception when attempting to communicate with SDC", e);\r
387             throw new SdcCommunicationException("Exception when attempting to communicate with SDC", e);\r
388         }\r
389     }\r
390 \r
391     private HttpURLConnection getSdcHttpUrlConnection(String userid, int postDataLength, String url, String content)\r
392             throws GeneralSecurityException {\r
393         try {\r
394             logger.info("userid=" + userid);\r
395             String basicAuth = getSdcBasicAuth();\r
396             String sdcXonapInstanceId = refProp.getStringValue("sdc.sdcX-InstanceID");\r
397             URL urlObj = new URL(url);\r
398             HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();\r
399             conn.setDoOutput(true);\r
400             conn.setRequestProperty(refProp.getStringValue(SDC_INSTANCE_ID_PROPERTY_NAME), sdcXonapInstanceId);\r
401             conn.setRequestProperty(HttpHeaders.AUTHORIZATION, basicAuth);\r
402             conn.setRequestProperty(HttpHeaders.CONTENT_TYPE, "application/json");\r
403             conn.setRequestProperty(HttpHeaders.CONTENT_MD5,\r
404                     Base64.getEncoder().encodeToString(DigestUtils.md5Hex(content).getBytes("UTF-8")));\r
405             conn.setRequestProperty("USER_ID", userid);\r
406             conn.setRequestMethod("POST");\r
407             conn.setRequestProperty("charset", "utf-8");\r
408             conn.setRequestProperty(HttpHeaders.CONTENT_LENGTH, Integer.toString(postDataLength));\r
409             conn.setUseCaches(false);\r
410             conn.setRequestProperty(refProp.getStringValue(SDC_REQUESTID_PROPERTY_NAME), LoggingUtils.getRequestId());\r
411             return conn;\r
412         } catch (IOException e) {\r
413             logger.error("Exception when attempting to open connection with SDC", e);\r
414             throw new SdcCommunicationException("Exception when attempting to open connection with SDC", e);\r
415         } catch (DecoderException e) {\r
416             logger.error("Exception when attempting to decode the Hex string", e);\r
417             throw new SdcCommunicationException("Exception when attempting to decode the Hex string", e);\r
418         } catch (GeneralSecurityException e) {\r
419             logger.error("Exception when attempting to decrypt the encrypted password", e);\r
420             throw new SdcCommunicationException("Exception when attempting to decrypt the encrypted password", e);\r
421         }\r
422     }\r
423 \r
424     private String getResponse(HttpURLConnection conn) {\r
425         try (InputStream is = getInputStream(conn)) {\r
426             try (BufferedReader in = new BufferedReader(new InputStreamReader(is))) {\r
427                 return IOUtils.toString(in);\r
428             }\r
429         } catch (IOException e) {\r
430             logger.error("Exception when attempting to open SDC response", e);\r
431             throw new SdcCommunicationException("Exception when attempting to open SDC response", e);\r
432         }\r
433     }\r
434 \r
435     private InputStream getInputStream(HttpURLConnection conn) {\r
436         try {\r
437             InputStream inStream = conn.getErrorStream();\r
438             if (inStream == null) {\r
439                 inStream = conn.getInputStream();\r
440             }\r
441             return inStream;\r
442         } catch (IOException e) {\r
443             logger.error("Exception when attempting to open SDC error stream", e);\r
444             throw new SdcCommunicationException("Exception when attempting to open SDC error stream", e);\r
445         }\r
446     }\r
447 \r
448     public CldsDBServiceCache getCldsDbServiceCacheUsingCldsServiceData(CldsServiceData cldsServiceData) {\r
449         try {\r
450             CldsDBServiceCache cldsDbServiceCache = new CldsDBServiceCache();\r
451             cldsDbServiceCache.setCldsDataInstream(cldsServiceData);\r
452             cldsDbServiceCache.setInvariantId(cldsServiceData.getServiceInvariantUUID());\r
453             cldsDbServiceCache.setServiceId(cldsServiceData.getServiceUUID());\r
454             return cldsDbServiceCache;\r
455         } catch (IOException e) {\r
456             logger.error("Exception when getting service in cache", e);\r
457             throw new SdcCommunicationException("Exception when getting service in cache", e);\r
458         }\r
459     }\r
460 \r
461     /**\r
462      * Check if the SDC Info in cache has expired.\r
463      * \r
464      * @param cldsServiceData\r
465      * @return\r
466      * @throws GeneralSecurityException\r
467      *             In case of issues with the decryting the encrypted password\r
468      * @throws DecoderException\r
469      *             In case of issues with the decoding of the Hex String\r
470      */\r
471     public boolean isCldsSdcCacheDataExpired(CldsServiceData cldsServiceData)\r
472             throws GeneralSecurityException, DecoderException {\r
473         boolean expired = false;\r
474         if (cldsServiceData != null && cldsServiceData.getServiceUUID() != null) {\r
475             String cachedServiceUuid = cldsServiceData.getServiceUUID();\r
476             String latestServiceUuid = getServiceUuidFromServiceInvariantId(cldsServiceData.getServiceInvariantUUID());\r
477             String defaultRecordAge = refProp.getStringValue("CLDS_SERVICE_CACHE_MAX_SECONDS");\r
478             if ((!cachedServiceUuid.equalsIgnoreCase(latestServiceUuid)) || (cldsServiceData.getAgeOfRecord() != null\r
479                     && cldsServiceData.getAgeOfRecord() > Long.parseLong(defaultRecordAge))) {\r
480                 expired = true;\r
481             }\r
482         } else {\r
483             expired = true;\r
484         }\r
485         return expired;\r
486     }\r
487 \r
488     /**\r
489      * Get the Service Data with Alarm Conditions for a given\r
490      * invariantServiceUuid.\r
491      * \r
492      * @param invariantServiceUuid\r
493      * @return\r
494      * @throws GeneralSecurityException\r
495      *             In case of issues with the decryting the encrypted password\r
496      * @throws DecoderException\r
497      *             In case of issues with the decoding of the Hex String\r
498      */\r
499     public CldsServiceData getCldsServiceDataWithAlarmConditions(String invariantServiceUuid)\r
500             throws GeneralSecurityException, DecoderException {\r
501         String url = refProp.getStringValue(SDC_SERVICE_URL_PROPERTY_NAME);\r
502         String catalogUrl = refProp.getStringValue(SDC_CATALOG_URL_PROPERTY_NAME);\r
503         String serviceUuid = getServiceUuidFromServiceInvariantId(invariantServiceUuid);\r
504         String serviceDetailUrl = url + "/" + serviceUuid + SDC_METADATA_URL_PREFIX;\r
505         String responseStr = getCldsServicesOrResourcesBasedOnURL(serviceDetailUrl, false);\r
506         ObjectMapper objectMapper = new ObjectMapper();\r
507         CldsServiceData cldsServiceData = new CldsServiceData();\r
508         if (responseStr != null) {\r
509             CldsSdcServiceDetail cldsSdcServiceDetail;\r
510             try {\r
511                 cldsSdcServiceDetail = objectMapper.readValue(responseStr, CldsSdcServiceDetail.class);\r
512             } catch (IOException e) {\r
513                 logger.error("Exception when decoding the CldsServiceData JSON from SDC", e);\r
514                 throw new SdcCommunicationException("Exception when decoding the CldsServiceData JSON from SDC", e);\r
515             }\r
516             // To remove duplicate resources from serviceDetail and add valid\r
517             // vfs to service\r
518             if (cldsSdcServiceDetail != null && cldsSdcServiceDetail.getResources() != null) {\r
519                 cldsServiceData.setServiceUUID(cldsSdcServiceDetail.getUuid());\r
520                 cldsServiceData.setServiceInvariantUUID(cldsSdcServiceDetail.getInvariantUUID());\r
521                 List<CldsSdcResource> cldsSdcResourceList = removeDuplicateSdcResourceInstances(\r
522                         cldsSdcServiceDetail.getResources());\r
523                 if (cldsSdcResourceList != null && !cldsSdcResourceList.isEmpty()) {\r
524                     List<CldsVfData> cldsVfDataList = new ArrayList<>();\r
525                     for (CldsSdcResource currCldsSdcResource : cldsSdcResourceList) {\r
526                         if (currCldsSdcResource != null && currCldsSdcResource.getResoucreType() != null\r
527                                 && "VF".equalsIgnoreCase(currCldsSdcResource.getResoucreType())) {\r
528                             CldsVfData currCldsVfData = new CldsVfData();\r
529                             currCldsVfData.setVfName(currCldsSdcResource.getResourceInstanceName());\r
530                             currCldsVfData.setVfInvariantResourceUUID(currCldsSdcResource.getResourceInvariantUUID());\r
531                             cldsVfDataList.add(currCldsVfData);\r
532                         }\r
533                     }\r
534                     cldsServiceData.setCldsVfs(cldsVfDataList);\r
535                     // For each vf in the list , add all vfc's\r
536                     getAllVfcForVfList(cldsVfDataList, catalogUrl);\r
537                     logger.info("value of cldsServiceData:" + cldsServiceData);\r
538                     logger.info("value of cldsServiceData:" + cldsServiceData.getServiceInvariantUUID());\r
539                 }\r
540             }\r
541         }\r
542         return cldsServiceData;\r
543     }\r
544 \r
545     private void getAllVfcForVfList(List<CldsVfData> cldsVfDataList, String catalogUrl)\r
546             throws GeneralSecurityException {\r
547         // todo : refact this..\r
548         if (cldsVfDataList != null && !cldsVfDataList.isEmpty()) {\r
549             List<CldsSdcResourceBasicInfo> allVfResources = getAllSdcVForVfcResourcesBasedOnResourceType(\r
550                     RESOURCE_VF_TYPE);\r
551             List<CldsSdcResourceBasicInfo> allVfcResources = getAllSdcVForVfcResourcesBasedOnResourceType(\r
552                     RESOURCE_VFC_TYPE);\r
553             allVfcResources.addAll(getAllSdcVForVfcResourcesBasedOnResourceType(RESOURCE_CVFC_TYPE));\r
554             for (CldsVfData currCldsVfData : cldsVfDataList) {\r
555                 if (currCldsVfData != null && currCldsVfData.getVfInvariantResourceUUID() != null) {\r
556                     String resourceUuid = getResourceUuidFromResourceInvariantUuid(\r
557                             currCldsVfData.getVfInvariantResourceUUID(), allVfResources);\r
558                     if (resourceUuid != null) {\r
559                         String vfResourceUuidUrl = catalogUrl + RESOURCE_URL_PREFIX + "/" + resourceUuid\r
560                                 + SDC_METADATA_URL_PREFIX;\r
561                         String vfResponse = getCldsServicesOrResourcesBasedOnURL(vfResourceUuidUrl, false);\r
562                         if (vfResponse != null) {\r
563                             // Below 2 line are to get the KPI(field path) data\r
564                             // associated with the VF's\r
565                             List<CldsVfKPIData> cldsVfKPIDataList = getFieldPathFromVF(vfResponse);\r
566                             currCldsVfData.setCldsKPIList(cldsVfKPIDataList);\r
567                             List<CldsVfcData> vfcDataListFromVfResponse = getVfcDataListFromVfResponse(vfResponse);\r
568                             if (vfcDataListFromVfResponse != null) {\r
569                                 currCldsVfData.setCldsVfcs(vfcDataListFromVfResponse);\r
570                                 if (!vfcDataListFromVfResponse.isEmpty()) {\r
571                                     // To get artifacts for every VFC and get\r
572                                     // alarm conditions from artifact\r
573                                     for (CldsVfcData currCldsVfcData : vfcDataListFromVfResponse) {\r
574                                         if (currCldsVfcData != null\r
575                                                 && currCldsVfcData.getVfcInvariantResourceUUID() != null) {\r
576                                             String resourceVfcUuid = getResourceUuidFromResourceInvariantUuid(\r
577                                                     currCldsVfcData.getVfcInvariantResourceUUID(), allVfcResources);\r
578                                             if (resourceVfcUuid != null) {\r
579                                                 String vfcResourceUuidUrl = catalogUrl + RESOURCE_URL_PREFIX + "/"\r
580                                                         + resourceVfcUuid + SDC_METADATA_URL_PREFIX;\r
581                                                 String vfcResponse = getCldsServicesOrResourcesBasedOnURL(\r
582                                                         vfcResourceUuidUrl, false);\r
583                                                 if (vfcResponse != null) {\r
584                                                     List<CldsAlarmCondition> alarmCondtionsFromVfc = getAlarmCondtionsFromVfc(\r
585                                                             vfcResponse);\r
586                                                     currCldsVfcData.setCldsAlarmConditions(alarmCondtionsFromVfc);\r
587                                                 }\r
588                                             } else {\r
589                                                 logger.info("No resourceVFC UUID found for given invariantID:"\r
590                                                         + currCldsVfcData.getVfcInvariantResourceUUID());\r
591                                             }\r
592                                         }\r
593                                     }\r
594                                 }\r
595                             }\r
596                         }\r
597                     } else {\r
598                         logger.info("No resourceUUID found for given invariantREsourceUUID:"\r
599                                 + currCldsVfData.getVfInvariantResourceUUID());\r
600                     }\r
601                 }\r
602             }\r
603         }\r
604     }\r
605 \r
606     private List<CldsVfcData> getVfcDataListFromVfResponse(String vfResponse) throws GeneralSecurityException {\r
607         ObjectMapper mapper = new ObjectMapper();\r
608         ObjectNode vfResponseNode;\r
609         try {\r
610             vfResponseNode = (ObjectNode) mapper.readTree(vfResponse);\r
611         } catch (IOException e) {\r
612             logger.error("Exception when decoding the JSON list of CldsVfcData", e);\r
613             return new ArrayList<>();\r
614         }\r
615         ArrayNode vfcArrayNode = (ArrayNode) vfResponseNode.get("resources");\r
616         List<CldsVfcData> cldsVfcDataList = new ArrayList<>();\r
617         if (vfcArrayNode != null) {\r
618             for (JsonNode vfcjsonNode : vfcArrayNode) {\r
619                 CldsVfcData currCldsVfcData = new CldsVfcData();\r
620                 ObjectNode currVfcNode = (ObjectNode) vfcjsonNode;\r
621                 TextNode resourceTypeNode = (TextNode) currVfcNode.get("resoucreType");\r
622                 if (resourceTypeNode != null && "VFC".equalsIgnoreCase(resourceTypeNode.textValue())) {\r
623                     TextNode vfcResourceName = (TextNode) currVfcNode.get("resourceInstanceName");\r
624                     TextNode vfcInvariantResourceUuid = (TextNode) currVfcNode.get("resourceInvariantUUID");\r
625                     currCldsVfcData.setVfcName(vfcResourceName.textValue());\r
626                     currCldsVfcData.setVfcInvariantResourceUUID(vfcInvariantResourceUuid.textValue());\r
627                     cldsVfcDataList.add(currCldsVfcData);\r
628                 } else if (resourceTypeNode != null && "CVFC".equalsIgnoreCase(resourceTypeNode.textValue())) {\r
629                     TextNode vfcResourceName = (TextNode) currVfcNode.get("resourceInstanceName");\r
630                     TextNode vfcInvariantResourceUuid = (TextNode) currVfcNode.get("resourceInvariantUUID");\r
631                     currCldsVfcData.setVfcName(vfcResourceName.textValue());\r
632                     currCldsVfcData.setVfcInvariantResourceUUID(vfcInvariantResourceUuid.textValue());\r
633                     cldsVfcDataList.add(currCldsVfcData);\r
634                     cldsVfcDataList.addAll(getVFCfromCVFC(currVfcNode.get("resourceUUID").textValue()));\r
635                 }\r
636             }\r
637         }\r
638         return cldsVfcDataList;\r
639     }\r
640 \r
641     private List<CldsVfcData> getVFCfromCVFC(String resourceUUID) throws GeneralSecurityException {\r
642         String catalogUrl = refProp.getStringValue(SDC_CATALOG_URL_PROPERTY_NAME);\r
643         List<CldsVfcData> cldsVfcDataList = new ArrayList<>();\r
644         if (resourceUUID != null) {\r
645             String vfcResourceUUIDUrl = catalogUrl + RESOURCE_URL_PREFIX + "/" + resourceUUID + SDC_METADATA_URL_PREFIX;\r
646             try {\r
647                 String vfcResponse = getCldsServicesOrResourcesBasedOnURL(vfcResourceUUIDUrl, false);\r
648                 ObjectMapper mapper = new ObjectMapper();\r
649                 ObjectNode vfResponseNode = (ObjectNode) mapper.readTree(vfcResponse);\r
650                 ArrayNode vfcArrayNode = (ArrayNode) vfResponseNode.get("resources");\r
651                 if (vfcArrayNode != null) {\r
652                     for (JsonNode vfcjsonNode : vfcArrayNode) {\r
653                         CldsVfcData currCldsVfcData = new CldsVfcData();\r
654                         ObjectNode currVfcNode = (ObjectNode) vfcjsonNode;\r
655                         TextNode resourceTypeNode = (TextNode) currVfcNode.get("resoucreType");\r
656                         if (resourceTypeNode != null && "VFC".equalsIgnoreCase(resourceTypeNode.textValue())) {\r
657                             TextNode vfcResourceName = (TextNode) currVfcNode.get("resourceInstanceName");\r
658                             TextNode vfcInvariantResourceUUID = (TextNode) currVfcNode.get("resourceInvariantUUID");\r
659                             currCldsVfcData.setVfcName(vfcResourceName.textValue());\r
660                             currCldsVfcData.setVfcInvariantResourceUUID(vfcInvariantResourceUUID.textValue());\r
661                             cldsVfcDataList.add(currCldsVfcData);\r
662                         }\r
663                     }\r
664                 }\r
665             } catch (IOException e) {\r
666                 logger.error("Exception during JSON analyzis", e);\r
667             }\r
668         }\r
669         return cldsVfcDataList;\r
670     }\r
671 \r
672     private String removeUnwantedBracesFromString(String id) {\r
673         return (id != null) ? id.replaceAll("\"", "") : "";\r
674     }\r
675 \r
676     private List<CldsAlarmCondition> getAlarmCondtionsFromVfc(String vfcResponse) throws GeneralSecurityException {\r
677         List<CldsAlarmCondition> cldsAlarmConditionList = new ArrayList<>();\r
678         ObjectMapper mapper = new ObjectMapper();\r
679         ObjectNode vfcResponseNode;\r
680         try {\r
681             vfcResponseNode = (ObjectNode) mapper.readTree(vfcResponse);\r
682         } catch (IOException e) {\r
683             logger.error("Exception when decoding the JSON list of CldsAlarmCondition", e);\r
684             return cldsAlarmConditionList;\r
685         }\r
686         ArrayNode artifactsArrayNode = (ArrayNode) vfcResponseNode.get("artifacts");\r
687         if (artifactsArrayNode != null && artifactsArrayNode.size() > 0) {\r
688             for (int index = 0; index < artifactsArrayNode.size(); index++) {\r
689                 ObjectNode currArtifactNode = (ObjectNode) artifactsArrayNode.get(index);\r
690                 TextNode artifactUrlNode = (TextNode) currArtifactNode.get("artifactURL");\r
691                 if (artifactUrlNode != null) {\r
692                     String responsesFromArtifactUrl = getResponsesFromArtifactUrl(artifactUrlNode.textValue());\r
693                     cldsAlarmConditionList.addAll(parseCsvToGetAlarmConditions(responsesFromArtifactUrl));\r
694                     logger.info(responsesFromArtifactUrl);\r
695                 }\r
696             }\r
697         }\r
698         return cldsAlarmConditionList;\r
699     }\r
700 \r
701     private List<CldsAlarmCondition> parseCsvToGetAlarmConditions(String allAlarmCondsValues) {\r
702         try {\r
703             List<CldsAlarmCondition> cldsAlarmConditionList = new ArrayList<>();\r
704             Reader alarmReader = new StringReader(allAlarmCondsValues);\r
705             Iterable<CSVRecord> records = CSVFormat.RFC4180.parse(alarmReader);\r
706             if (records != null) {\r
707                 Iterator<CSVRecord> it = records.iterator();\r
708                 if (it.hasNext()) {\r
709                     it.next();\r
710                 }\r
711                 it.forEachRemaining(record -> processRecord(cldsAlarmConditionList, record));\r
712             }\r
713             return cldsAlarmConditionList;\r
714         } catch (IOException e) {\r
715             logger.error("Exception when attempting to parse the CSV containing the alarm", e);\r
716             return new ArrayList<>();\r
717         }\r
718     }\r
719 \r
720     // Method to get the artifact for any particular VF\r
721     private List<CldsVfKPIData> getFieldPathFromVF(String vfResponse) throws GeneralSecurityException {\r
722         List<CldsVfKPIData> cldsVfKPIDataList = new ArrayList<>();\r
723         ObjectMapper mapper = new ObjectMapper();\r
724         ObjectNode vfResponseNode;\r
725         try {\r
726             vfResponseNode = (ObjectNode) mapper.readTree(vfResponse);\r
727         } catch (IOException e) {\r
728             logger.error("Exception when decoding the JSON list of CldsVfKPIData", e);\r
729             return cldsVfKPIDataList;\r
730         }\r
731         ArrayNode artifactsArrayNode = (ArrayNode) vfResponseNode.get("artifacts");\r
732         if (artifactsArrayNode != null && artifactsArrayNode.size() > 0) {\r
733             for (int index = 0; index < artifactsArrayNode.size(); index++) {\r
734                 ObjectNode currArtifactNode = (ObjectNode) artifactsArrayNode.get(index);\r
735                 TextNode artifactUrlNode = (TextNode) currArtifactNode.get("artifactURL");\r
736                 TextNode artifactNameNode = (TextNode) currArtifactNode.get("artifactName");\r
737                 String artifactName = "";\r
738                 if (artifactNameNode != null) {\r
739                     artifactName = artifactNameNode.textValue();\r
740                     artifactName = artifactName.substring(artifactName.lastIndexOf('.') + 1);\r
741                 }\r
742                 if (artifactUrlNode != null && "csv".equalsIgnoreCase(artifactName)) {\r
743                     String responsesFromArtifactUrl = getResponsesFromArtifactUrl(artifactUrlNode.textValue());\r
744                     cldsVfKPIDataList.addAll(parseCsvToGetFieldPath(responsesFromArtifactUrl));\r
745                     logger.info(responsesFromArtifactUrl);\r
746                 }\r
747             }\r
748         }\r
749         return cldsVfKPIDataList;\r
750     }\r
751 \r
752     private CldsVfKPIData convertCsvRecordToKpiData(CSVRecord record) {\r
753         if (record.size() < 6) {\r
754             logger.debug("invalid csv field path Record,total columns less than 6: " + record);\r
755             return null;\r
756         }\r
757         if (StringUtils.isBlank(record.get(1)) || StringUtils.isBlank(record.get(3))\r
758                 || StringUtils.isBlank(record.get(5))) {\r
759             logger.debug("Invalid csv field path Record,one of column is having blank value : " + record);\r
760             return null;\r
761         }\r
762         CldsVfKPIData cldsVfKPIData = new CldsVfKPIData();\r
763         cldsVfKPIData.setNfNamingCode(record.get(0).trim());\r
764         cldsVfKPIData.setNfNamingValue(record.get(1).trim());\r
765         cldsVfKPIData.setFieldPath(record.get(2).trim());\r
766         cldsVfKPIData.setFieldPathValue(record.get(3).trim());\r
767         cldsVfKPIData.setThresholdName(record.get(4).trim());\r
768         cldsVfKPIData.setThresholdValue(record.get(5).trim());\r
769         return cldsVfKPIData;\r
770     }\r
771 \r
772     // Method to get the artifactURL Data and set the CldsVfKPIData node\r
773     private List<CldsVfKPIData> parseCsvToGetFieldPath(String allFieldPathValues) {\r
774         try {\r
775             List<CldsVfKPIData> cldsVfKPIDataList = new ArrayList<>();\r
776             Reader alarmReader = new StringReader(allFieldPathValues);\r
777             Iterable<CSVRecord> records = CSVFormat.RFC4180.parse(alarmReader);\r
778             if (records != null) {\r
779                 for (CSVRecord record : records) {\r
780                     CldsVfKPIData kpiData = this.convertCsvRecordToKpiData(record);\r
781                     if (kpiData != null) {\r
782                         cldsVfKPIDataList.add(kpiData);\r
783                     }\r
784                 }\r
785             }\r
786             return cldsVfKPIDataList;\r
787         } catch (IOException e) {\r
788             logger.error("Exception when attempting to parse the CSV containing the alarm kpi data", e);\r
789             return new ArrayList<>();\r
790         }\r
791     }\r
792 \r
793     private void processRecord(List<CldsAlarmCondition> cldsAlarmConditionList, CSVRecord record) {\r
794         if (record == null) {\r
795             return;\r
796         }\r
797         if (record.size() < 5) {\r
798             logger.debug("invalid csv alarm Record,total columns less than 5: " + record);\r
799             return;\r
800         }\r
801         if (StringUtils.isBlank(record.get(1)) || StringUtils.isBlank(record.get(3))\r
802                 || StringUtils.isBlank(record.get(4))) {\r
803             logger.debug("invalid csv alarm Record,one of column is having blank value : " + record);\r
804             return;\r
805         }\r
806         CldsAlarmCondition cldsAlarmCondition = new CldsAlarmCondition();\r
807         cldsAlarmCondition.setEventSourceType(record.get(1));\r
808         cldsAlarmCondition.setEventName(record.get(2));\r
809         cldsAlarmCondition.setAlarmConditionKey(record.get(3));\r
810         cldsAlarmCondition.setSeverity(record.get(4));\r
811         cldsAlarmConditionList.add(cldsAlarmCondition);\r
812     }\r
813 \r
814     /**\r
815      * Get the responses for the current artifact from the artifacts URL.\r
816      * \r
817      * @param artifactsUrl\r
818      * @return\r
819      * @throws GeneralSecurityException\r
820      */\r
821     public String getResponsesFromArtifactUrl(String artifactsUrl) throws GeneralSecurityException {\r
822         String hostUrl = refProp.getStringValue("sdc.hostUrl");\r
823         String artifactsUrlReworked = artifactsUrl.replaceAll("\"", "");\r
824         String artifactUrl = hostUrl + artifactsUrlReworked;\r
825         logger.info("value of artifactURl:" + artifactUrl);\r
826         String currArtifactResponse = getCldsServicesOrResourcesBasedOnURL(artifactUrl, true);\r
827         logger.info("value of artifactResponse:" + currArtifactResponse);\r
828         return currArtifactResponse;\r
829     }\r
830 \r
831     /**\r
832      * Service to services/resources/artifacts from sdc.Pass alarmConditions as\r
833      * true to get alarm conditons from artifact url and else it is false\r
834      * \r
835      * @param url\r
836      * @param alarmConditions\r
837      * @return\r
838      * @throws GeneralSecurityException\r
839      *             In case of issue when decrypting the SDC password\r
840      * \r
841      */\r
842     public String getCldsServicesOrResourcesBasedOnURL(String url, boolean alarmConditions)\r
843             throws GeneralSecurityException {\r
844         Date startTime = new Date();\r
845         try {\r
846             LoggingUtils.setTargetContext("SDC", "getCldsServicesOrResourcesBasedOnURL");\r
847             String urlReworked = removeUnwantedBracesFromString(url);\r
848             URL urlObj = new URL(urlReworked);\r
849             HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();\r
850             String basicAuth = getSdcBasicAuth();\r
851             conn.setRequestProperty(refProp.getStringValue(SDC_INSTANCE_ID_PROPERTY_NAME), SDC_INSTANCE_ID_CLAMP);\r
852             conn.setRequestProperty(HttpHeaders.AUTHORIZATION, basicAuth);\r
853             conn.setRequestProperty(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");\r
854             conn.setRequestProperty(refProp.getStringValue(SDC_REQUESTID_PROPERTY_NAME), LoggingUtils.getRequestId());\r
855             conn.setRequestMethod("GET");\r
856             int responseCode = conn.getResponseCode();\r
857             logger.info("Sdc resource url - " + urlReworked + " , responseCode=" + responseCode);\r
858             try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {\r
859                 String response = IOUtils.toString(in);\r
860                 LoggingUtils.setResponseContext("0", "Get sdc resources success", this.getClass().getName());\r
861                 return response;\r
862             }\r
863         } catch (IOException e) {\r
864             LoggingUtils.setResponseContext("900", "Get sdc resources failed", this.getClass().getName());\r
865             LoggingUtils.setErrorContext("900", "Get sdc resources error");\r
866             logger.error("Exception occurred during query to SDC", e);\r
867             return "";\r
868         } catch (DecoderException e) {\r
869             logger.error("Exception when attempting to decode the Hex string", e);\r
870             throw new SdcCommunicationException("Exception when attempting to decode the Hex string", e);\r
871         } catch (GeneralSecurityException e) {\r
872             logger.error("Exception when attempting to decrypt the encrypted password", e);\r
873             throw new SdcCommunicationException("Exception when attempting to decrypt the encrypted password", e);\r
874         } finally {\r
875             LoggingUtils.setTimeContext(startTime, new Date());\r
876             metricsLogger.info("getCldsServicesOrResourcesBasedOnURL completed");\r
877         }\r
878     }\r
879 \r
880     /**\r
881      * To create properties object by using cldsServicedata.\r
882      *\r
883      * @param globalProps\r
884      * @param cldsServiceData\r
885      * @return\r
886      */\r
887     public String createPropertiesObjectByUUID(String globalProps, CldsServiceData cldsServiceData) {\r
888         String totalPropsStr;\r
889         ObjectMapper mapper = new ObjectMapper();\r
890         ObjectNode globalPropsJson;\r
891         if (cldsServiceData != null && cldsServiceData.getServiceUUID() != null) {\r
892             // Objectnode to save all byservice, byvf , byvfc and byalarm nodes\r
893             ObjectNode byIdObjectNode = mapper.createObjectNode();\r
894             // To create vf ResourceUUID node with serviceInvariantUUID\r
895             ObjectNode invariantUuidObjectNodeWithVf = createVfObjectNodeByServiceInvariantUuid(mapper,\r
896                     cldsServiceData);\r
897             byIdObjectNode.putPOJO("byService", invariantUuidObjectNodeWithVf);\r
898             // To create byVf and vfcResourceNode with vfResourceUUID\r
899             ObjectNode vfcObjectNodeByVfUuid = createVfcObjectNodeByVfUuid(mapper, cldsServiceData.getCldsVfs());\r
900             byIdObjectNode.putPOJO("byVf", vfcObjectNodeByVfUuid);\r
901             // To create byKpi\r
902             ObjectNode kpiObjectNode = mapper.createObjectNode();\r
903             if (cldsServiceData.getCldsVfs() != null && !cldsServiceData.getCldsVfs().isEmpty()) {\r
904                 for (CldsVfData currCldsVfData : cldsServiceData.getCldsVfs()) {\r
905                     if (currCldsVfData != null) {\r
906                         createKpiObjectNodeByVfUuid(mapper, kpiObjectNode, currCldsVfData.getCldsKPIList());\r
907                     }\r
908                 }\r
909             }\r
910             byIdObjectNode.putPOJO("byKpi", kpiObjectNode);\r
911             // To create byVfc and alarmCondition with vfcResourceUUID\r
912             ObjectNode vfcResourceUuidObjectNode = mapper.createObjectNode();\r
913             if (cldsServiceData.getCldsVfs() != null && !cldsServiceData.getCldsVfs().isEmpty()) {\r
914                 for (CldsVfData currCldsVfData : cldsServiceData.getCldsVfs()) {\r
915                     if (currCldsVfData != null) {\r
916                         createAlarmCondObjectNodeByVfcUuid(mapper, vfcResourceUuidObjectNode,\r
917                                 currCldsVfData.getCldsVfcs());\r
918                     }\r
919                 }\r
920             }\r
921             byIdObjectNode.putPOJO("byVfc", vfcResourceUuidObjectNode);\r
922             // To create byAlarmCondition with alarmConditionKey\r
923             List<CldsAlarmCondition> allAlarmConditions = getAllAlarmConditionsFromCldsServiceData(cldsServiceData,\r
924                     "alarmCondition");\r
925             ObjectNode alarmCondObjectNodeByAlarmKey = createAlarmCondObjectNodeByAlarmKey(mapper, allAlarmConditions);\r
926             byIdObjectNode.putPOJO("byAlarmCondition", alarmCondObjectNodeByAlarmKey);\r
927             // To create byAlertDescription with AlertDescription\r
928             List<CldsAlarmCondition> allAlertDescriptions = getAllAlarmConditionsFromCldsServiceData(cldsServiceData,\r
929                     "alertDescription");\r
930             ObjectNode alertDescObjectNodeByAlert = createAlarmCondObjectNodeByAlarmKey(mapper, allAlertDescriptions);\r
931             byIdObjectNode.putPOJO("byAlertDescription", alertDescObjectNodeByAlert);\r
932             globalPropsJson = decodeGlobalProp(globalProps, mapper);\r
933             globalPropsJson.putPOJO("shared", byIdObjectNode);\r
934             logger.info("value of objNode:" + globalPropsJson);\r
935         } else {\r
936             /**\r
937              * to create json with total properties when no serviceUUID passed\r
938              */\r
939             globalPropsJson = decodeGlobalProp(globalProps, mapper);\r
940         }\r
941         totalPropsStr = globalPropsJson.toString();\r
942         return totalPropsStr;\r
943     }\r
944 \r
945     private ObjectNode decodeGlobalProp(String globalProps, ObjectMapper mapper) {\r
946         try {\r
947             return (ObjectNode) mapper.readValue(globalProps, JsonNode.class);\r
948         } catch (IOException e) {\r
949             logger.error("Exception occurred during decoding of the global props, returning an empty objectNode", e);\r
950             return mapper.createObjectNode();\r
951         }\r
952     }\r
953 \r
954     /**\r
955      * Method to get alarm conditions/alert description from Service Data.\r
956      * \r
957      * @param cldsServiceData\r
958      *            CldsServiceData the Service Data to analyze\r
959      * @param eventName\r
960      *            The String event name that will be used to filter the alarm\r
961      *            list\r
962      * @return The list of CldsAlarmCondition for the event name specified\r
963      */\r
964     public List<CldsAlarmCondition> getAllAlarmConditionsFromCldsServiceData(CldsServiceData cldsServiceData,\r
965             String eventName) {\r
966         List<CldsAlarmCondition> alarmCondList = new ArrayList<>();\r
967         if (cldsServiceData != null && cldsServiceData.getCldsVfs() != null\r
968                 && !cldsServiceData.getCldsVfs().isEmpty()) {\r
969             for (CldsVfData currCldsVfData : cldsServiceData.getCldsVfs()) {\r
970                 alarmCondList.addAll(getAllAlarmConditionsFromCldsVfData(currCldsVfData, eventName));\r
971             }\r
972         }\r
973         return alarmCondList;\r
974     }\r
975 \r
976     /**\r
977      * Method to get alarm conditions/alert description from VF Data.\r
978      * \r
979      * @param currCldsVfData\r
980      *            The Vf Data to analyze\r
981      * @param eventName\r
982      *            The String event name that will be used to filter the alarm\r
983      *            list\r
984      * @return The list of CldsAlarmCondition for the event name specified\r
985      */\r
986     private List<CldsAlarmCondition> getAllAlarmConditionsFromCldsVfData(CldsVfData currCldsVfData, String eventName) {\r
987         List<CldsAlarmCondition> alarmCondList = new ArrayList<>();\r
988         if (currCldsVfData != null && currCldsVfData.getCldsVfcs() != null && !currCldsVfData.getCldsVfcs().isEmpty()) {\r
989             for (CldsVfcData currCldsVfcData : currCldsVfData.getCldsVfcs()) {\r
990                 alarmCondList.addAll(getAllAlarmConditionsFromCldsVfcData(currCldsVfcData, eventName));\r
991             }\r
992         }\r
993         return alarmCondList;\r
994     }\r
995 \r
996     /**\r
997      * Method to get alarm conditions/alert description from VFC Data.\r
998      * \r
999      * @param currCldsVfcData\r
1000      *            The VfC Data to analyze\r
1001      * @param eventName\r
1002      *            The String event name that will be used to filter the alarm\r
1003      *            list\r
1004      * @return The list of CldsAlarmCondition for the event name specified\r
1005      */\r
1006     private List<CldsAlarmCondition> getAllAlarmConditionsFromCldsVfcData(CldsVfcData currCldsVfcData,\r
1007             String eventName) {\r
1008         List<CldsAlarmCondition> alarmCondList = new ArrayList<>();\r
1009         if (currCldsVfcData != null && currCldsVfcData.getCldsAlarmConditions() != null\r
1010                 && !currCldsVfcData.getCldsAlarmConditions().isEmpty()) {\r
1011             for (CldsAlarmCondition currCldsAlarmCondition : currCldsVfcData.getCldsAlarmConditions()) {\r
1012                 if (currCldsAlarmCondition != null\r
1013                         && currCldsAlarmCondition.getEventName().equalsIgnoreCase(eventName)) {\r
1014                     alarmCondList.add(currCldsAlarmCondition);\r
1015                 }\r
1016             }\r
1017         }\r
1018         return alarmCondList;\r
1019     }\r
1020 \r
1021     private ObjectNode createAlarmCondObjectNodeByAlarmKey(ObjectMapper mapper,\r
1022             List<CldsAlarmCondition> cldsAlarmCondList) {\r
1023         ObjectNode alarmCondKeyNode = mapper.createObjectNode();\r
1024         if (cldsAlarmCondList != null && !cldsAlarmCondList.isEmpty()) {\r
1025             for (CldsAlarmCondition currCldsAlarmCondition : cldsAlarmCondList) {\r
1026                 if (currCldsAlarmCondition != null) {\r
1027                     ObjectNode alarmCondNode = mapper.createObjectNode();\r
1028                     alarmCondNode.put("eventSourceType", currCldsAlarmCondition.getEventSourceType());\r
1029                     alarmCondNode.put("eventSeverity", currCldsAlarmCondition.getSeverity());\r
1030                     alarmCondKeyNode.putPOJO(currCldsAlarmCondition.getAlarmConditionKey(), alarmCondNode);\r
1031                 }\r
1032             }\r
1033         } else {\r
1034             ObjectNode alarmCondNode = mapper.createObjectNode();\r
1035             alarmCondNode.put("eventSourceType", "");\r
1036             alarmCondNode.put("eventSeverity", "");\r
1037             alarmCondKeyNode.putPOJO("", alarmCondNode);\r
1038         }\r
1039         return alarmCondKeyNode;\r
1040     }\r
1041 \r
1042     private ObjectNode createVfObjectNodeByServiceInvariantUuid(ObjectMapper mapper, CldsServiceData cldsServiceData) {\r
1043         ObjectNode invariantUuidObjectNode = mapper.createObjectNode();\r
1044         ObjectNode vfObjectNode = mapper.createObjectNode();\r
1045         ObjectNode vfUuidNode = mapper.createObjectNode();\r
1046         List<CldsVfData> cldsVfsList = cldsServiceData.getCldsVfs();\r
1047         if (cldsVfsList != null && !cldsVfsList.isEmpty()) {\r
1048             for (CldsVfData currCldsVfData : cldsVfsList) {\r
1049                 if (currCldsVfData != null) {\r
1050                     vfUuidNode.put(currCldsVfData.getVfInvariantResourceUUID(), currCldsVfData.getVfName());\r
1051                 }\r
1052             }\r
1053         } else {\r
1054             vfUuidNode.put("", "");\r
1055         }\r
1056         vfObjectNode.putPOJO("vf", vfUuidNode);\r
1057         invariantUuidObjectNode.putPOJO(cldsServiceData.getServiceInvariantUUID(), vfObjectNode);\r
1058         return invariantUuidObjectNode;\r
1059     }\r
1060 \r
1061     private void createKpiObjectNodeByVfUuid(ObjectMapper mapper, ObjectNode vfResourceUuidObjectNode,\r
1062             List<CldsVfKPIData> cldsVfKpiDataList) {\r
1063         if (cldsVfKpiDataList != null && !cldsVfKpiDataList.isEmpty()) {\r
1064             for (CldsVfKPIData currCldsVfKpiData : cldsVfKpiDataList) {\r
1065                 if (currCldsVfKpiData != null) {\r
1066                     ObjectNode thresholdNameObjectNode = mapper.createObjectNode();\r
1067                     ObjectNode fieldPathObjectNode = mapper.createObjectNode();\r
1068                     ObjectNode nfNamingCodeNode = mapper.createObjectNode();\r
1069                     fieldPathObjectNode.put(currCldsVfKpiData.getFieldPathValue(),\r
1070                             currCldsVfKpiData.getFieldPathValue());\r
1071                     nfNamingCodeNode.put(currCldsVfKpiData.getNfNamingValue(), currCldsVfKpiData.getNfNamingValue());\r
1072                     thresholdNameObjectNode.putPOJO("fieldPath", fieldPathObjectNode);\r
1073                     thresholdNameObjectNode.putPOJO("nfNamingCode", nfNamingCodeNode);\r
1074                     vfResourceUuidObjectNode.putPOJO(currCldsVfKpiData.getThresholdValue(), thresholdNameObjectNode);\r
1075                 }\r
1076             }\r
1077         }\r
1078     }\r
1079 \r
1080     private void createAlarmCondObjectNodeByVfcUuid(ObjectMapper mapper, ObjectNode vfcResourceUuidObjectNode,\r
1081             List<CldsVfcData> cldsVfcDataList) {\r
1082         ObjectNode vfcObjectNode = mapper.createObjectNode();\r
1083         ObjectNode alarmCondNode = mapper.createObjectNode();\r
1084         ObjectNode alertDescNode = mapper.createObjectNode();\r
1085         if (cldsVfcDataList != null && !cldsVfcDataList.isEmpty()) {\r
1086             for (CldsVfcData currCldsVfcData : cldsVfcDataList) {\r
1087                 if (currCldsVfcData != null) {\r
1088                     if (currCldsVfcData.getCldsAlarmConditions() != null\r
1089                             && !currCldsVfcData.getCldsAlarmConditions().isEmpty()) {\r
1090                         for (CldsAlarmCondition currCldsAlarmCondition : currCldsVfcData.getCldsAlarmConditions()) {\r
1091                             if ("alarmCondition".equalsIgnoreCase(currCldsAlarmCondition.getEventName())) {\r
1092                                 alarmCondNode.put(currCldsAlarmCondition.getAlarmConditionKey(),\r
1093                                         currCldsAlarmCondition.getAlarmConditionKey());\r
1094                             } else {\r
1095                                 alertDescNode.put(currCldsAlarmCondition.getAlarmConditionKey(),\r
1096                                         currCldsAlarmCondition.getAlarmConditionKey());\r
1097                             }\r
1098                         }\r
1099                     }\r
1100                     vfcObjectNode.putPOJO("alarmCondition", alarmCondNode);\r
1101                     vfcObjectNode.putPOJO("alertDescription", alertDescNode);\r
1102                     vfcResourceUuidObjectNode.putPOJO(currCldsVfcData.getVfcInvariantResourceUUID(), vfcObjectNode);\r
1103                 }\r
1104             }\r
1105         } else {\r
1106             alarmCondNode.put("", "");\r
1107             vfcObjectNode.putPOJO("alarmCondition", alarmCondNode);\r
1108             alertDescNode.put("", "");\r
1109             vfcObjectNode.putPOJO("alertDescription", alarmCondNode);\r
1110             vfcResourceUuidObjectNode.putPOJO("", vfcObjectNode);\r
1111         }\r
1112     }\r
1113 \r
1114     /**\r
1115      * Method to create vfc and kpi nodes inside vf node\r
1116      * \r
1117      * @param mapper\r
1118      * @param cldsVfDataList\r
1119      * @return\r
1120      */\r
1121     private ObjectNode createVfcObjectNodeByVfUuid(ObjectMapper mapper, List<CldsVfData> cldsVfDataList) {\r
1122         ObjectNode vfUuidObjectNode = mapper.createObjectNode();\r
1123         if (cldsVfDataList != null && !cldsVfDataList.isEmpty()) {\r
1124             for (CldsVfData currCldsVfData : cldsVfDataList) {\r
1125                 if (currCldsVfData != null) {\r
1126                     ObjectNode vfObjectNode = mapper.createObjectNode();\r
1127                     ObjectNode vfcUuidNode = mapper.createObjectNode();\r
1128                     ObjectNode kpiObjectNode = mapper.createObjectNode();\r
1129                     if (currCldsVfData.getCldsVfcs() != null && !currCldsVfData.getCldsVfcs().isEmpty()) {\r
1130                         for (CldsVfcData currCldsVfcData : currCldsVfData.getCldsVfcs()) {\r
1131                             if (currCldsVfcData.getCldsAlarmConditions() != null\r
1132                                     && !currCldsVfcData.getCldsAlarmConditions().isEmpty()) {\r
1133                                 vfcUuidNode.put(currCldsVfcData.getVfcInvariantResourceUUID(),\r
1134                                         currCldsVfcData.getVfcName());\r
1135                             }\r
1136                         }\r
1137                     } else {\r
1138                         vfcUuidNode.put("", "");\r
1139                     }\r
1140                     if (currCldsVfData.getCldsKPIList() != null && !currCldsVfData.getCldsKPIList().isEmpty()) {\r
1141                         for (CldsVfKPIData currCldsVfKPIData : currCldsVfData.getCldsKPIList()) {\r
1142                             kpiObjectNode.put(currCldsVfKPIData.getThresholdValue(),\r
1143                                     currCldsVfKPIData.getThresholdValue());\r
1144                         }\r
1145                     } else {\r
1146                         kpiObjectNode.put("", "");\r
1147                     }\r
1148                     vfObjectNode.putPOJO("vfc", vfcUuidNode);\r
1149                     vfObjectNode.putPOJO("kpi", kpiObjectNode);\r
1150                     vfUuidObjectNode.putPOJO(currCldsVfData.getVfInvariantResourceUUID(), vfObjectNode);\r
1151                 }\r
1152             }\r
1153         } else {\r
1154             ObjectNode vfcUuidNode = mapper.createObjectNode();\r
1155             vfcUuidNode.put("", "");\r
1156             ObjectNode vfcObjectNode = mapper.createObjectNode();\r
1157             vfcObjectNode.putPOJO("vfc", vfcUuidNode);\r
1158             vfUuidObjectNode.putPOJO("", vfcObjectNode);\r
1159         }\r
1160         return vfUuidObjectNode;\r
1161     }\r
1162 \r
1163     /**\r
1164      * This method searches the equivalent artifact UUID for a specific\r
1165      * artifactName in a SdcServiceDetail.\r
1166      * \r
1167      * @param cldsSdcServiceDetail\r
1168      *            The SdcServiceDetail that will be analyzed\r
1169      * @param artifactName\r
1170      *            The artifact name that will be searched\r
1171      * @return The artifact UUID found\r
1172      */\r
1173     public String getArtifactIdIfArtifactAlreadyExists(CldsSdcServiceDetail cldsSdcServiceDetail, String artifactName) {\r
1174         String artifactUuid = null;\r
1175         boolean artifactExists = false;\r
1176         if (cldsSdcServiceDetail != null && cldsSdcServiceDetail.getResources() != null\r
1177                 && !cldsSdcServiceDetail.getResources().isEmpty()) {\r
1178             for (CldsSdcResource currCldsSdcResource : cldsSdcServiceDetail.getResources()) {\r
1179                 if (artifactExists) {\r
1180                     break;\r
1181                 }\r
1182                 if (currCldsSdcResource != null && currCldsSdcResource.getArtifacts() != null\r
1183                         && !currCldsSdcResource.getArtifacts().isEmpty()) {\r
1184                     for (CldsSdcArtifact currCldsSdcArtifact : currCldsSdcResource.getArtifacts()) {\r
1185                         if (currCldsSdcArtifact != null && currCldsSdcArtifact.getArtifactName() != null\r
1186                                 && currCldsSdcArtifact.getArtifactName().equalsIgnoreCase(artifactName)) {\r
1187                             artifactUuid = currCldsSdcArtifact.getArtifactUUID();\r
1188                             artifactExists = true;\r
1189                             break;\r
1190                         }\r
1191                     }\r
1192                 }\r
1193             }\r
1194         }\r
1195         return artifactUuid;\r
1196     }\r
1197 \r
1198     /**\r
1199      * To get all sdc VF/VFC Resources basic info.\r
1200      * \r
1201      * @param resourceType\r
1202      *            The resourceType\r
1203      * @return The list of CldsSdcResourceBasicInfo\r
1204      * @throws GeneralSecurityException\r
1205      *             In case of issue when decryting the SDC password\r
1206      * \r
1207      */\r
1208     private List<CldsSdcResourceBasicInfo> getAllSdcVForVfcResourcesBasedOnResourceType(String resourceType)\r
1209             throws GeneralSecurityException {\r
1210         String catalogUrl = refProp.getStringValue(SDC_CATALOG_URL_PROPERTY_NAME);\r
1211         String resourceUrl = catalogUrl + "resources?resourceType=" + resourceType;\r
1212         String allSdcVfcResources = getCldsServicesOrResourcesBasedOnURL(resourceUrl, false);\r
1213         return removeDuplicateSdcResourceBasicInfo(getAllSdcResourcesListFromJson(allSdcVfcResources));\r
1214     }\r
1215 \r
1216     private String getResourceUuidFromResourceInvariantUuid(String resourceInvariantUuid,\r
1217             List<CldsSdcResourceBasicInfo> resourceInfoList) {\r
1218         String resourceUuid = null;\r
1219         if (resourceInfoList != null && !resourceInfoList.isEmpty()) {\r
1220             for (CldsSdcResourceBasicInfo currResource : resourceInfoList) {\r
1221                 if (currResource != null && currResource.getInvariantUUID() != null && currResource.getUuid() != null\r
1222                         && currResource.getInvariantUUID().equalsIgnoreCase(resourceInvariantUuid)) {\r
1223                     resourceUuid = currResource.getUuid();\r
1224                     break;\r
1225                 }\r
1226             }\r
1227         }\r
1228         return resourceUuid;\r
1229     }\r
1230 \r
1231     /**\r
1232      * Method to get service invariant uuid from model properties.\r
1233      * \r
1234      * @param props\r
1235      *            The Clds model properties\r
1236      * @return The Service Id\r
1237      */\r
1238     private String getServiceInvariantUuidFromProps(ModelProperties props) {\r
1239         String invariantUuid = "";\r
1240         Global globalProps = props.getGlobal();\r
1241         if (globalProps != null && globalProps.getService() != null) {\r
1242             invariantUuid = globalProps.getService();\r
1243         }\r
1244         return invariantUuid;\r
1245     }\r
1246 \r
1247     /**\r
1248      * This method upload the BluePrint to SDC.\r
1249      * \r
1250      * @param prop\r
1251      *            The Clds model Properties\r
1252      * @param userid\r
1253      *            The user id for SDC\r
1254      * @param sdcReqUrlsList\r
1255      *            The list of SDC URL to try\r
1256      * @param formattedSdcReq\r
1257      *            The blueprint to upload\r
1258      * @param formattedSdcLocationReq\r
1259      *            THe location Blueprint to upload\r
1260      * @param artifactName\r
1261      *            The artifact name from where we can get the Artifact UUID\r
1262      * @param locationArtifactName\r
1263      *            The location artifact name from where we can get the Artifact\r
1264      *            UUID\r
1265      * @throws GeneralSecurityException\r
1266      *             In case of issues with the decryting the encrypted password\r
1267      * @throws DecoderException\r
1268      *             In case of issues with the decoding of the Hex String\r
1269      */\r
1270     public void uploadToSdc(ModelProperties prop, String userid, List<String> sdcReqUrlsList, String formattedSdcReq,\r
1271             String formattedSdcLocationReq, String artifactName, String locationArtifactName)\r
1272             throws GeneralSecurityException, DecoderException {\r
1273         logger.info("userid=" + userid);\r
1274         String serviceInvariantUuid = getServiceInvariantUuidFromProps(prop);\r
1275         if (sdcReqUrlsList != null && !sdcReqUrlsList.isEmpty()) {\r
1276             for (String url : sdcReqUrlsList) {\r
1277                 if (url != null) {\r
1278                     String originalServiceUuid = getServiceUuidFromServiceInvariantId(serviceInvariantUuid);\r
1279                     logger.info("ServiceUUID used before upload in url:" + originalServiceUuid);\r
1280                     String sdcServicesInformation = getSdcServicesInformation(originalServiceUuid);\r
1281                     CldsSdcServiceDetail cldsSdcServiceDetail = getCldsSdcServiceDetailFromJson(sdcServicesInformation);\r
1282                     String uploadedArtifactUuid = getArtifactIdIfArtifactAlreadyExists(cldsSdcServiceDetail,\r
1283                             artifactName);\r
1284                     // Upload artifacts to sdc\r
1285                     String updateUrl = uploadedArtifactUuid != null ? url + "/" + uploadedArtifactUuid : url;\r
1286                     String responseStr = uploadArtifactToSdc(prop, userid, updateUrl, formattedSdcReq);\r
1287                     logger.info("value of sdc Response of uploading to sdc :" + responseStr);\r
1288                     String updatedServiceUuid = getServiceUuidFromServiceInvariantId(serviceInvariantUuid);\r
1289                     if (!originalServiceUuid.equalsIgnoreCase(updatedServiceUuid)) {\r
1290                         url = url.replace(originalServiceUuid, updatedServiceUuid);\r
1291                     }\r
1292                     logger.info("ServiceUUID used after upload in ulr:" + updatedServiceUuid);\r
1293                     sdcServicesInformation = getSdcServicesInformation(updatedServiceUuid);\r
1294                     cldsSdcServiceDetail = getCldsSdcServiceDetailFromJson(sdcServicesInformation);\r
1295                     uploadedArtifactUuid = getArtifactIdIfArtifactAlreadyExists(cldsSdcServiceDetail,\r
1296                             locationArtifactName);\r
1297                     // To send location information also to sdc\r
1298                     updateUrl = uploadedArtifactUuid != null ? url + "/" + uploadedArtifactUuid : url;\r
1299                     responseStr = uploadArtifactToSdc(prop, userid, updateUrl, formattedSdcLocationReq);\r
1300                     logger.info("value of sdc Response of uploading location to sdc :" + responseStr);\r
1301                 }\r
1302             }\r
1303         }\r
1304     }\r
1305 }\r