Initial commit for AAI-UI(sparky-backend)
[aai/sparky-be.git] / src / main / java / org / openecomp / sparky / util / NodeUtils.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25
26 package org.openecomp.sparky.util;
27
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.lang.Thread.UncaughtExceptionHandler;
33 import java.nio.ByteBuffer;
34 import java.security.SecureRandom;
35 import java.text.ParseException;
36 import java.text.SimpleDateFormat;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.Date;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.TimeZone;
46 import java.util.concurrent.ExecutorService;
47 import java.util.concurrent.Executors;
48 import java.util.concurrent.ThreadFactory;
49 import java.util.concurrent.TimeUnit;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
52
53 import javax.servlet.http.HttpServletRequest;
54 import javax.xml.stream.XMLStreamConstants;
55
56 import org.openecomp.cl.api.Logger;
57 import org.openecomp.sparky.logging.AaiUiMsgs;
58 import org.openecomp.sparky.viewandinspect.config.TierSupportUiConstants;
59
60 import com.fasterxml.jackson.core.JsonProcessingException;
61 import com.fasterxml.jackson.databind.JsonNode;
62 import com.fasterxml.jackson.databind.ObjectMapper;
63 import com.fasterxml.jackson.databind.ObjectWriter;
64 import com.fasterxml.jackson.databind.SerializationFeature;
65 import com.google.common.util.concurrent.ThreadFactoryBuilder;
66
67
68 /**
69  * The Class NodeUtils.
70  */
71 public class NodeUtils {
72   private static SecureRandom sRandom = new SecureRandom();
73   
74   public static synchronized String getRandomTxnId(){
75       byte bytes[] = new byte[6];
76       sRandom.nextBytes(bytes);
77       return Integer.toUnsignedString(ByteBuffer.wrap(bytes).getInt());
78   }
79
80   /**
81    * Builds the depth padding.
82    *
83    * @param depth the depth
84    * @return the string
85    */
86   public static String buildDepthPadding(int depth) {
87     StringBuilder sb = new StringBuilder(32);
88
89     for (int x = 0; x < depth; x++) {
90       sb.append("   ");
91     }
92
93     return sb.toString();
94   }
95
96   /**
97    * Checks if is numeric.
98    *
99    * @param numberStr the number str
100    * @return true, if is numeric
101    */
102   public static boolean isNumeric(String numberStr) {
103
104     try {
105       Double.parseDouble(numberStr);
106     } catch (Exception exc) {
107       return false;
108     }
109
110     return true;
111
112   }
113
114   /**
115    * Creates the named executor.
116    *
117    * @param name the name
118    * @param numWorkers the num workers
119    * @param logger the logger
120    * @return the executor service
121    */
122   public static ExecutorService createNamedExecutor(String name, int numWorkers, final Logger logger) {
123     UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
124
125       @Override
126       public void uncaughtException(Thread thread, Throwable exc) {
127
128         logger.error(AaiUiMsgs.ERROR_GENERIC, thread.getName() + ": " + exc);
129
130       }
131     };
132
133     ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(name + "-%d")
134         .setUncaughtExceptionHandler(uncaughtExceptionHandler).build();
135
136     return Executors.newScheduledThreadPool(numWorkers + 1, namedThreadFactory);
137   }
138
139   /**
140    * Calculate edit attribute uri.
141    *
142    * @param link the link
143    * @return the string
144    */
145   public static String calculateEditAttributeUri(String link) {
146     String uri = null;
147
148     if (link != null) {
149
150       Pattern pattern = Pattern.compile(TierSupportUiConstants.URI_VERSION_REGEX_PATTERN);
151       Matcher matcher = pattern.matcher(link);
152       if (matcher.find()) {
153         uri = link.substring(matcher.end());
154       }
155     }
156     return uri;
157   }
158
159   /**
160    * Generate unique sha digest.
161    *
162    * @param keys the keys
163    * @return the string
164    */
165   public static String generateUniqueShaDigest(String... keys) {
166
167     if ((keys == null) || keys.length == 0) {
168       return null;
169     }
170
171     final String keysStr = Arrays.asList(keys).toString();
172     final String hashedId = org.apache.commons.codec.digest.DigestUtils.sha256Hex(keysStr);
173
174     return hashedId;
175   }
176
177   /**
178    * Gets the node field as text.
179    *
180    * @param node the node
181    * @param fieldName the field name
182    * @return the node field as text
183    */
184   public static String getNodeFieldAsText(JsonNode node, String fieldName) {
185
186     String fieldValue = null;
187
188     JsonNode valueNode = node.get(fieldName);
189
190     if (valueNode != null) {
191       fieldValue = valueNode.asText();
192     }
193
194     return fieldValue;
195   }
196
197   private static final String ENTITY_RESOURCE_KEY_FORMAT = "%s.%s";
198
199   /**
200    * Convert a millisecond duration to a string format
201    * 
202    * @param millis A duration to convert to a string form
203    * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
204    */
205
206   private static final String TIME_BREAK_DOWN_FORMAT =
207       "[ %d days, %d hours, %d minutes, %d seconds ]";
208
209   /**
210    * Gets the duration breakdown.
211    *
212    * @param millis the millis
213    * @return the duration breakdown
214    */
215   public static String getDurationBreakdown(long millis) {
216
217     if (millis < 0) {
218       return String.format(TIME_BREAK_DOWN_FORMAT, 0, 0, 0, 0);
219     }
220
221     long days = TimeUnit.MILLISECONDS.toDays(millis);
222     millis -= TimeUnit.DAYS.toMillis(days);
223     long hours = TimeUnit.MILLISECONDS.toHours(millis);
224     millis -= TimeUnit.HOURS.toMillis(hours);
225     long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
226     millis -= TimeUnit.MINUTES.toMillis(minutes);
227     long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
228
229     return String.format(TIME_BREAK_DOWN_FORMAT, days, hours, minutes, seconds);
230
231   }
232
233   /**
234    * Checks if is equal.
235    *
236    * @param n1 the n 1
237    * @param n2 the n 2
238    * @return true, if is equal
239    */
240   public static boolean isEqual(JsonNode n1, JsonNode n2) {
241
242     /*
243      * due to the inherent nature of json being unordered, comparing object representations of the
244      * same keys and values but different order makes comparison challenging. Let's try an
245      * experiment where we compare the structure of the json, and then simply compare the sorted
246      * order of that structure which should be good enough for what we are trying to accomplish.
247      */
248
249     TreeWalker walker = new TreeWalker();
250     List<String> n1Paths = new ArrayList<String>();
251     List<String> n2Paths = new ArrayList<String>();
252
253     walker.walkTree(n1Paths, n1);
254     walker.walkTree(n2Paths, n2);
255
256     Collections.sort(n1Paths);
257     Collections.sort(n2Paths);
258
259     return n1Paths.equals(n2Paths);
260
261   }
262
263   /**
264    * Concat array.
265    *
266    * @param list the list
267    * @return the string
268    */
269   public static String concatArray(List<String> list) {
270     return concatArray(list, " ");
271   }
272
273   /**
274    * Concat array.
275    *
276    * @param list the list
277    * @param delimiter the delimiter
278    * @return the string
279    */
280   public static String concatArray(List<String> list, String delimiter) {
281
282     if (list == null || list.size() == 0) {
283       return "";
284     }
285
286     StringBuilder result = new StringBuilder(64);
287
288     boolean firstValue = true;
289
290     for (String item : list) {
291
292       if (firstValue) {
293         result.append(item);
294         firstValue = false;
295       } else {
296         result.append(delimiter).append(item);
297       }
298
299     }
300
301     return result.toString();
302
303   }
304
305   /**
306    * Concat array.
307    *
308    * @param values the values
309    * @return the string
310    */
311   public static String concatArray(String[] values) {
312
313     if (values == null || values.length == 0) {
314       return "";
315     }
316
317     StringBuilder result = new StringBuilder(64);
318
319     boolean firstValue = true;
320
321     for (String item : values) {
322
323       if (firstValue) {
324         result.append(item);
325         firstValue = false;
326       } else {
327         result.append(".").append(item);
328       }
329
330     }
331
332     return result.toString();
333
334   }
335
336   /**
337    * Builds the entity resource key.
338    *
339    * @param entityType the entity type
340    * @param resourceId the resource id
341    * @return the string
342    */
343   public static String buildEntityResourceKey(String entityType, String resourceId) {
344     return String.format(ENTITY_RESOURCE_KEY_FORMAT, entityType, resourceId);
345   }
346
347   /**
348    * Extract resource id from link.
349    *
350    * @param link the link
351    * @return the string
352    */
353   public static String extractResourceIdFromLink(String link) {
354
355     if (link == null) {
356       return null;
357     }
358
359     int linkLength = link.length();
360     if (linkLength == 0) {
361       return null;
362     }
363
364     /*
365      * if the last character != / then we need to change the lastIndex position
366      */
367
368     int startIndex = 0;
369     String resourceId = null;
370     if ("/".equals(link.substring(linkLength - 1))) {
371       // Use-case:
372       // https://aai-ext1.test.att.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS/
373       startIndex = link.lastIndexOf("/", linkLength - 2);
374       resourceId = link.substring(startIndex + 1, linkLength - 1);
375     } else {
376       // Use-case:
377       // https://aai-ext1.test.att.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS
378       startIndex = link.lastIndexOf("/");
379       resourceId = link.substring(startIndex + 1, linkLength);
380     }
381
382     String result = null;
383
384     if (resourceId != null) {
385       try {
386         result = java.net.URLDecoder.decode(resourceId, "UTF-8");
387       } catch (Exception exc) {
388         /*
389          * if there is a failure decoding the parameter we will just return the original value.
390          */
391         result = resourceId;
392       }
393     }
394
395     return result;
396
397   }
398
399   /**
400    * Gets the xml stream constant as str.
401    *
402    * @param value the value
403    * @return the xml stream constant as str
404    */
405   public static String getXmlStreamConstantAsStr(int value) {
406     switch (value) {
407       case XMLStreamConstants.ATTRIBUTE:
408         return "ATTRIBUTE";
409       case XMLStreamConstants.CDATA:
410         return "CDATA";
411       case XMLStreamConstants.CHARACTERS:
412         return "CHARACTERS";
413       case XMLStreamConstants.COMMENT:
414         return "COMMENT";
415       case XMLStreamConstants.DTD:
416         return "DTD";
417       case XMLStreamConstants.END_DOCUMENT:
418         return "END_DOCUMENT";
419       case XMLStreamConstants.END_ELEMENT:
420         return "END_ELEMENT";
421       case XMLStreamConstants.ENTITY_DECLARATION:
422         return "ENTITY_DECLARATION";
423       case XMLStreamConstants.ENTITY_REFERENCE:
424         return "ENTITY_REFERENCE";
425       case XMLStreamConstants.NAMESPACE:
426         return "NAMESPACE";
427       case XMLStreamConstants.NOTATION_DECLARATION:
428         return "NOTATION_DECLARATION";
429       case XMLStreamConstants.PROCESSING_INSTRUCTION:
430         return "PROCESSING_INSTRUCTION";
431       case XMLStreamConstants.SPACE:
432         return "SPACE";
433       case XMLStreamConstants.START_DOCUMENT:
434         return "START_DOCUMENT";
435       case XMLStreamConstants.START_ELEMENT:
436         return "START_ELEMENT";
437
438       default:
439         return "Unknown(" + value + ")";
440     }
441   }
442
443   /**
444    * Convert object to json.
445    *
446    * @param object the object
447    * @param pretty the pretty
448    * @return the string
449    * @throws JsonProcessingException the json processing exception
450    */
451   public static String convertObjectToJson(Object object, boolean pretty)
452       throws JsonProcessingException {
453     ObjectWriter ow = null;
454
455     ObjectMapper mapper = new ObjectMapper();
456     mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
457     
458     if (pretty) {
459       ow = mapper.writer().withDefaultPrettyPrinter();
460
461     } else {
462       ow = mapper.writer();
463     }
464
465     return ow.writeValueAsString(object);
466   }
467
468   /**
469    * Convert json str to json node.
470    *
471    * @param jsonStr the json str
472    * @return the json node
473    * @throws IOException Signals that an I/O exception has occurred.
474    */
475   public static JsonNode convertJsonStrToJsonNode(String jsonStr) throws IOException {
476     ObjectMapper mapper = new ObjectMapper();
477     if (jsonStr == null || jsonStr.length() == 0) {
478       return null;
479     }
480
481     return mapper.readTree(jsonStr);
482   }
483
484   /**
485    * Convert object to xml.
486    *
487    * @param object the object
488    * @return the string
489    * @throws JsonProcessingException the json processing exception
490    */
491   public static String convertObjectToXml(Object object) throws JsonProcessingException {
492     ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
493     String jsonOutput = ow.writeValueAsString(object);
494
495     if (jsonOutput == null) {
496       return null;
497     }
498
499     return JsonXmlConverter.convertJsontoXml(jsonOutput);
500
501   }
502
503   /**
504    * Extract objects by key.
505    *
506    * @param node the node
507    * @param searchKey the search key
508    * @param foundObjects the found objects
509    */
510   public static void extractObjectsByKey(JsonNode node, String searchKey,
511       Collection<JsonNode> foundObjects) {
512
513     if ( node == null ) {
514       return;
515     }
516     
517     if (node.isObject()) {
518       Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
519
520       while (nodeIterator.hasNext()) {
521         Map.Entry<String, JsonNode> entry = nodeIterator.next();
522         if (!entry.getValue().isValueNode()) {
523           extractObjectsByKey(entry.getValue(), searchKey, foundObjects);
524         }
525
526         String name = entry.getKey();
527         if (name.equalsIgnoreCase(searchKey)) {
528
529           JsonNode entryNode = entry.getValue();
530
531           if (entryNode.isArray()) {
532
533             Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
534             while (arrayItemsIterator.hasNext()) {
535               foundObjects.add(arrayItemsIterator.next());
536             }
537
538           } else {
539             foundObjects.add(entry.getValue());
540           }
541
542
543         }
544       }
545     } else if (node.isArray()) {
546       Iterator<JsonNode> arrayItemsIterator = node.elements();
547       while (arrayItemsIterator.hasNext()) {
548         extractObjectsByKey(arrayItemsIterator.next(), searchKey, foundObjects);
549       }
550
551     }
552
553   }
554
555   /**
556    * Convert array into list.
557    *
558    * @param node the node
559    * @param instances the instances
560    */
561   public static void convertArrayIntoList(JsonNode node, Collection<JsonNode> instances) {
562
563     if (node.isArray()) {
564       Iterator<JsonNode> arrayItemsIterator = node.elements();
565       while (arrayItemsIterator.hasNext()) {
566         instances.add(arrayItemsIterator.next());
567       }
568
569     } else {
570       instances.add(node);
571     }
572
573   }
574
575   /**
576    * Extract field values from object.
577    *
578    * @param node the node
579    * @param attributesToExtract the attributes to extract
580    * @param fieldValues the field values
581    */
582   public static void extractFieldValuesFromObject(JsonNode node,
583       Collection<String> attributesToExtract, Collection<String> fieldValues) {
584
585     if (node == null) {
586       return;
587     }
588
589     if (node.isObject()) {
590
591       JsonNode valueNode = null;
592
593       for (String attrToExtract : attributesToExtract) {
594
595         valueNode = node.get(attrToExtract);
596
597         if (valueNode != null) {
598
599           if (valueNode.isValueNode()) {
600             fieldValues.add(valueNode.asText());
601           }
602         }
603       }
604     }
605   }
606
607   /**
608    * Extract field value from object.
609    *
610    * @param node the node
611    * @param fieldName the field name
612    * @return the string
613    */
614   public static String extractFieldValueFromObject(JsonNode node, String fieldName) {
615
616     if (node == null) {
617       return null;
618     }
619
620     if (node.isObject()) {
621
622       JsonNode valueNode = node.get(fieldName);
623
624       if (valueNode != null) {
625
626         if (valueNode.isValueNode()) {
627           return valueNode.asText();
628         }
629       }
630
631     }
632     return null;
633
634   }
635
636   /**
637    * Format timestamp.
638    *
639    * @param timestamp the timestamp
640    * @return the string
641    */
642   public static String formatTimestamp(String timestamp) {
643     try {
644       SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
645       originalFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
646       Date toDate = originalFormat.parse(timestamp);
647       SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
648       newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
649       return newFormat.format(toDate);
650
651     } catch (ParseException pe) {
652       return timestamp;
653     }
654   }
655   
656   /**
657    * Gets the HttpRequest payload.
658    *
659    * @param request the request
660    * @return the body
661    * @throws IOException Signals that an I/O exception has occurred.
662    */
663   public static String getBody(HttpServletRequest request) throws IOException {
664
665     String body = null;
666     StringBuilder stringBuilder = new StringBuilder();
667     BufferedReader bufferedReader = null;
668
669     try {
670       InputStream inputStream = request.getInputStream();
671       if (inputStream != null) {
672         bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
673         char[] charBuffer = new char[128];
674         int bytesRead = -1;
675         while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
676           stringBuilder.append(charBuffer, 0, bytesRead);
677         }
678       } else {
679         stringBuilder.append("");
680       }
681     } catch (IOException ex) {
682       throw ex;
683     } finally {
684       if (bufferedReader != null) {
685         try {
686           bufferedReader.close();
687         } catch (IOException ex) {
688           throw ex;
689         }
690       }
691     }
692
693     body = stringBuilder.toString();
694     return body;
695   }
696
697   /**
698    * The main method.
699    *
700    * @param args the arguments
701    * @throws ParseException the parse exception
702    */
703   public static void main(String[] args) throws ParseException {
704     String date = "20170110T112312Z";
705     SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'hhmmss'Z'");
706     Date toDate = originalFormat.parse(date);
707     SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss'Z'");
708     System.out.println(newFormat.format(toDate));
709
710   }
711
712
713
714 }