2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.aai.sparky.util;
23 import java.io.BufferedReader;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.lang.Thread.UncaughtExceptionHandler;
29 import java.nio.ByteBuffer;
30 import java.security.SecureRandom;
31 import java.sql.Timestamp;
32 import java.text.ParseException;
33 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Date;
39 import java.util.Iterator;
40 import java.util.List;
42 import java.util.TimeZone;
43 import java.util.concurrent.ExecutorService;
44 import java.util.concurrent.Executors;
45 import java.util.concurrent.ThreadFactory;
46 import java.util.concurrent.TimeUnit;
47 import java.util.regex.Matcher;
48 import java.util.regex.Pattern;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.xml.stream.XMLStreamConstants;
53 import org.onap.aai.cl.api.Logger;
54 import org.onap.aai.sparky.logging.AaiUiMsgs;
55 import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
56 import org.restlet.Request;
58 import com.fasterxml.jackson.core.JsonProcessingException;
59 import com.fasterxml.jackson.databind.JsonNode;
60 import com.fasterxml.jackson.databind.ObjectMapper;
61 import com.fasterxml.jackson.databind.ObjectWriter;
62 import com.fasterxml.jackson.databind.SerializationFeature;
63 import com.fasterxml.jackson.databind.ser.FilterProvider;
64 import com.google.common.util.concurrent.ThreadFactoryBuilder;
68 * The Class NodeUtils.
70 public class NodeUtils {
71 private static SecureRandom sRandom = new SecureRandom();
73 private static final Pattern URL_VERSION_PREFIX = Pattern.compile("/v[0-9]+/(.*)");
74 private static final Pattern OXM_VERSION_PREFIX = Pattern.compile(".*_v([0-9]+).*");
75 private static final Pattern GIZMO_VERSION_PREFIX = Pattern.compile("[/]*services/inventory/v[0-9]+/(.*)");
76 private static final Pattern GIZMO_RELATIONSHIP_VERSION_PREFIX = Pattern.compile("services/inventory/relationships/v[0-9]+/(.*)");
79 public static synchronized String getRandomTxnId(){
80 byte bytes[] = new byte[6];
81 sRandom.nextBytes(bytes);
82 return Integer.toUnsignedString(ByteBuffer.wrap(bytes).getInt());
86 * Builds the depth padding.
88 * @param depth the depth
91 public static String buildDepthPadding(int depth) {
92 StringBuilder sb = new StringBuilder(32);
94 for (int x = 0; x < depth; x++) {
101 public static String extractOxmVersionFromPath(String filePath) {
105 Matcher m = OXM_VERSION_PREFIX.matcher(filePath);
109 if ( m.groupCount() >= 1) {
114 } catch (Exception e) {
122 public static String extractRawPathWithoutVersion(String selfLinkUri) {
126 String rawPath = new URI(selfLinkUri).getRawPath();
128 Matcher m = URL_VERSION_PREFIX.matcher(rawPath);
132 if ( m.groupCount() >= 1) {
137 } catch (Exception e) {
144 public static String extractRawGizmoPathWithoutVersion(String resourceLink) {
148 String rawPath = new URI(resourceLink).getRawPath();
150 Matcher m = GIZMO_VERSION_PREFIX.matcher(rawPath);
154 if ( m.groupCount() >= 1) {
159 } catch (Exception e) {
166 public static String extractRawGizmoRelationshipPathWithoutVersion(String resourceLink) {
170 String rawPath = new URI(resourceLink).getRawPath();
172 Matcher m = GIZMO_RELATIONSHIP_VERSION_PREFIX.matcher(rawPath);
176 if ( m.groupCount() >= 1) {
181 } catch (Exception e) {
192 * Checks if is numeric.
194 * @param numberStr the number str
195 * @return true, if is numeric
197 public static boolean isNumeric(String numberStr) {
200 Double.parseDouble(numberStr);
201 } catch (Exception exc) {
210 * Creates the named executor.
212 * @param name the name
213 * @param numWorkers the num workers
214 * @param logger the logger
215 * @return the executor service
217 public static ExecutorService createNamedExecutor(String name, int numWorkers, final Logger logger) {
218 UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
221 public void uncaughtException(Thread thread, Throwable exc) {
223 logger.error(AaiUiMsgs.ERROR_GENERIC, thread.getName() + ": " + exc);
228 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(name + "-%d")
229 .setUncaughtExceptionHandler(uncaughtExceptionHandler).build();
231 return Executors.newScheduledThreadPool(numWorkers + 1, namedThreadFactory);
235 public static String calculateEditAttributeUri(String link) {
240 Pattern pattern = Pattern.compile(SparkyConstants.URI_VERSION_REGEX_PATTERN);
241 Matcher matcher = pattern.matcher(link);
242 if (matcher.find()) {
243 uri = link.substring(matcher.end());
251 * Generate unique sha digest.
253 * @param keys the keys
256 public static String generateUniqueShaDigest(String... keys) {
258 if ((keys == null) || keys.length == 0) {
262 final String keysStr = Arrays.asList(keys).toString();
263 final String hashedId = org.apache.commons.codec.digest.DigestUtils.sha256Hex(keysStr);
269 * Gets the node field as text.
271 * @param node the node
272 * @param fieldName the field name
273 * @return the node field as text
275 public static String getNodeFieldAsText(JsonNode node, String fieldName) {
277 String fieldValue = null;
279 JsonNode valueNode = node.get(fieldName);
281 if (valueNode != null) {
282 fieldValue = valueNode.asText();
288 private static final String ENTITY_RESOURCE_KEY_FORMAT = "%s.%s";
291 * Convert a millisecond duration to a string format
293 * @param millis A duration to convert to a string form
294 * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
297 private static final String TIME_BREAK_DOWN_FORMAT =
298 "[ %d days, %d hours, %d minutes, %d seconds ]";
301 * Gets the duration breakdown.
303 * @param millis the millis
304 * @return the duration breakdown
306 public static String getDurationBreakdown(long millis) {
309 return String.format(TIME_BREAK_DOWN_FORMAT, 0, 0, 0, 0);
312 long days = TimeUnit.MILLISECONDS.toDays(millis);
313 millis -= TimeUnit.DAYS.toMillis(days);
314 long hours = TimeUnit.MILLISECONDS.toHours(millis);
315 millis -= TimeUnit.HOURS.toMillis(hours);
316 long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
317 millis -= TimeUnit.MINUTES.toMillis(minutes);
318 long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
320 return String.format(TIME_BREAK_DOWN_FORMAT, days, hours, minutes, seconds);
325 * Checks if is equal.
329 * @return true, if is equal
331 public static boolean isEqual(JsonNode n1, JsonNode n2) {
334 * due to the inherent nature of json being unordered, comparing object representations of the
335 * same keys and values but different order makes comparison challenging. Let's try an
336 * experiment where we compare the structure of the json, and then simply compare the sorted
337 * order of that structure which should be good enough for what we are trying to accomplish.
340 TreeWalker walker = new TreeWalker();
341 List<String> n1Paths = new ArrayList<String>();
342 List<String> n2Paths = new ArrayList<String>();
344 walker.walkTree(n1Paths, n1);
345 walker.walkTree(n2Paths, n2);
347 Collections.sort(n1Paths);
348 Collections.sort(n2Paths);
350 return n1Paths.equals(n2Paths);
357 * @param list the list
360 public static String concatArray(List<String> list) {
361 return concatArray(list, " ");
364 private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
366 public static String getCurrentTimeStamp() {
367 SimpleDateFormat dateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
368 Timestamp timestamp = new Timestamp(System.currentTimeMillis());
369 return dateFormat.format(timestamp);
375 * @param list the list
376 * @param delimiter the delimiter
379 public static String concatArray(List<String> list, String delimiter) {
381 if (list == null || list.size() == 0) {
385 StringBuilder result = new StringBuilder(64);
387 boolean firstValue = true;
389 for (String item : list) {
395 result.append(delimiter).append(item);
400 return result.toString();
407 * @param values the values
410 public static String concatArray(String[] values) {
412 if (values == null || values.length == 0) {
416 StringBuilder result = new StringBuilder(64);
418 boolean firstValue = true;
420 for (String item : values) {
426 result.append(".").append(item);
431 return result.toString();
436 * Builds the entity resource key.
438 * @param entityType the entity type
439 * @param resourceId the resource id
442 public static String buildEntityResourceKey(String entityType, String resourceId) {
443 return String.format(ENTITY_RESOURCE_KEY_FORMAT, entityType, resourceId);
447 * Extract resource id from link.
449 * @param link the link
452 public static String extractResourceIdFromLink(String link) {
458 int linkLength = link.length();
459 if (linkLength == 0) {
464 * if the last character != / then we need to change the lastIndex position
468 String resourceId = null;
469 if ("/".equals(link.substring(linkLength - 1))) {
471 // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1/
472 startIndex = link.lastIndexOf("/", linkLength - 2);
473 resourceId = link.substring(startIndex + 1, linkLength - 1);
476 // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1
477 startIndex = link.lastIndexOf("/");
478 resourceId = link.substring(startIndex + 1, linkLength);
481 String result = null;
483 if (resourceId != null) {
485 result = java.net.URLDecoder.decode(resourceId, "UTF-8");
486 } catch (Exception exc) {
488 * if there is a failure decoding the parameter we will just return the original value.
499 * Gets the xml stream constant as str.
501 * @param value the value
502 * @return the xml stream constant as str
504 public static String getXmlStreamConstantAsStr(int value) {
506 case XMLStreamConstants.ATTRIBUTE:
508 case XMLStreamConstants.CDATA:
510 case XMLStreamConstants.CHARACTERS:
512 case XMLStreamConstants.COMMENT:
514 case XMLStreamConstants.DTD:
516 case XMLStreamConstants.END_DOCUMENT:
517 return "END_DOCUMENT";
518 case XMLStreamConstants.END_ELEMENT:
519 return "END_ELEMENT";
520 case XMLStreamConstants.ENTITY_DECLARATION:
521 return "ENTITY_DECLARATION";
522 case XMLStreamConstants.ENTITY_REFERENCE:
523 return "ENTITY_REFERENCE";
524 case XMLStreamConstants.NAMESPACE:
526 case XMLStreamConstants.NOTATION_DECLARATION:
527 return "NOTATION_DECLARATION";
528 case XMLStreamConstants.PROCESSING_INSTRUCTION:
529 return "PROCESSING_INSTRUCTION";
530 case XMLStreamConstants.SPACE:
532 case XMLStreamConstants.START_DOCUMENT:
533 return "START_DOCUMENT";
534 case XMLStreamConstants.START_ELEMENT:
535 return "START_ELEMENT";
538 return "Unknown(" + value + ")";
543 * Convert object to json.
545 * @param object the object
546 * @param pretty the pretty
548 * @throws JsonProcessingException the json processing exception
550 public static String convertObjectToJson(Object object, boolean pretty)
551 throws JsonProcessingException {
552 ObjectWriter ow = null;
554 ObjectMapper mapper = new ObjectMapper();
555 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
558 ow = mapper.writer().withDefaultPrettyPrinter();
561 ow = mapper.writer();
564 return ow.writeValueAsString(object);
568 * Convert object to json by selectively choosing certain fields thru filters.
570 * based on request type we might need to send different serialization of the UiViewFilterEntity
572 * @param object the object
573 * @param pretty the pretty
575 * @throws JsonProcessingException the json processing exception
577 public static String convertObjectToJson(Object object, boolean pretty, FilterProvider filters)
578 throws JsonProcessingException {
579 ObjectWriter ow = null;
581 ObjectMapper mapper = new ObjectMapper();
582 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
585 ow = mapper.writer(filters).withDefaultPrettyPrinter();
588 ow = mapper.writer(filters);
591 return ow.writeValueAsString(object);
596 * Convert json str to json node.
598 * @param jsonStr the json str
599 * @return the json node
600 * @throws IOException Signals that an I/O exception has occurred.
602 public static JsonNode convertJsonStrToJsonNode(String jsonStr) throws IOException {
603 ObjectMapper mapper = new ObjectMapper();
604 if (jsonStr == null || jsonStr.length() == 0) {
608 return mapper.readTree(jsonStr);
612 * Convert object to xml.
614 * @param object the object
616 * @throws JsonProcessingException the json processing exception
618 public static String convertObjectToXml(Object object) throws JsonProcessingException {
619 ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
620 String jsonOutput = ow.writeValueAsString(object);
622 if (jsonOutput == null) {
626 return JsonXmlConverter.convertJsonToXml(jsonOutput);
631 * Extract objects by key.
633 * @param node the node
634 * @param searchKey the search key
635 * @param foundObjects the found objects
637 public static void extractObjectsByKey(JsonNode node, String searchKey,
638 Collection<JsonNode> foundObjects) {
640 if ( node == null ) {
644 if (node.isObject()) {
645 Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
647 while (nodeIterator.hasNext()) {
648 Map.Entry<String, JsonNode> entry = nodeIterator.next();
649 if (!entry.getValue().isValueNode()) {
650 extractObjectsByKey(entry.getValue(), searchKey, foundObjects);
653 String name = entry.getKey();
654 if (name.equalsIgnoreCase(searchKey)) {
656 JsonNode entryNode = entry.getValue();
658 if (entryNode.isArray()) {
660 Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
661 while (arrayItemsIterator.hasNext()) {
662 foundObjects.add(arrayItemsIterator.next());
666 foundObjects.add(entry.getValue());
672 } else if (node.isArray()) {
673 Iterator<JsonNode> arrayItemsIterator = node.elements();
674 while (arrayItemsIterator.hasNext()) {
675 extractObjectsByKey(arrayItemsIterator.next(), searchKey, foundObjects);
681 public static String extractObjectValueByKey(JsonNode node, String searchKey) {
687 if (node.isObject()) {
688 Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
690 while (nodeIterator.hasNext()) {
691 Map.Entry<String, JsonNode> entry = nodeIterator.next();
692 if (!entry.getValue().isValueNode()) {
693 return extractObjectValueByKey(entry.getValue(), searchKey);
696 String name = entry.getKey();
697 if (name.equalsIgnoreCase(searchKey)) {
699 JsonNode entryNode = entry.getValue();
701 if (entryNode.isArray()) {
703 Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
704 while (arrayItemsIterator.hasNext()) {
705 return arrayItemsIterator.next().asText();
709 return entry.getValue().asText();
715 } else if (node.isArray()) {
716 Iterator<JsonNode> arrayItemsIterator = node.elements();
717 while (arrayItemsIterator.hasNext()) {
718 return extractObjectValueByKey(arrayItemsIterator.next(), searchKey);
728 * Convert array into list.
730 * @param node the node
731 * @param instances the instances
733 public static void convertArrayIntoList(JsonNode node, Collection<JsonNode> instances) {
735 if (node.isArray()) {
736 Iterator<JsonNode> arrayItemsIterator = node.elements();
737 while (arrayItemsIterator.hasNext()) {
738 instances.add(arrayItemsIterator.next());
748 * Extract field values from object.
750 * @param node the node
751 * @param attributesToExtract the attributes to extract
752 * @param fieldValues the field values
754 public static void extractFieldValuesFromObject(JsonNode node,
755 Collection<String> attributesToExtract, Collection<String> fieldValues) {
761 if (node.isObject()) {
763 JsonNode valueNode = null;
765 for (String attrToExtract : attributesToExtract) {
767 valueNode = node.get(attrToExtract);
769 if (valueNode != null) {
771 if (valueNode.isValueNode()) {
772 fieldValues.add(valueNode.asText());
780 * Extract field value from object.
782 * @param node the node
783 * @param fieldName the field name
786 public static String extractFieldValueFromObject(JsonNode node, String fieldName) {
792 if (node.isObject()) {
794 JsonNode valueNode = node.get(fieldName);
796 if (valueNode != null) {
798 if (valueNode.isValueNode()) {
799 return valueNode.asText();
811 * @param timestamp the timestamp
814 public static String formatTimestamp(String timestamp) {
816 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
817 originalFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
818 Date toDate = originalFormat.parse(timestamp);
819 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
820 newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
821 return newFormat.format(toDate);
823 } catch (ParseException pe) {
829 * Gets the HttpRequest payload.
831 * @param request the request
833 * @throws IOException Signals that an I/O exception has occurred.
835 public static String getBody(HttpServletRequest request) throws IOException {
836 InputStream inputStream = request.getInputStream();
837 return getBodyFromStream(inputStream);
843 * Gets the Restlet Request payload.
845 * @param request the request
847 * @throws IOException Signals that an I/O exception has occurred.
849 public static String getBody(Request request) throws IOException {
850 InputStream inputStream = request.getEntity().getStream();
851 return getBodyFromStream(inputStream);
856 * Gets the payload from the input stream of a request.
858 * @param request the request
860 * @throws IOException Signals that an I/O exception has occurred.
862 public static String getBodyFromStream(InputStream inputStream) throws IOException {
865 StringBuilder stringBuilder = new StringBuilder();
866 BufferedReader bufferedReader = null;
869 if (inputStream != null) {
870 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
871 char[] charBuffer = new char[128];
873 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
874 stringBuilder.append(charBuffer, 0, bytesRead);
877 stringBuilder.append("");
879 } catch (IOException ex) {
882 if (bufferedReader != null) {
883 bufferedReader.close();
887 body = stringBuilder.toString();
895 * @param args the arguments
896 * @throws ParseException the parse exception
898 public static void main(String[] args) throws ParseException {
899 String date = "20170110T112312Z";
900 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'hhmmss'Z'");
901 Date toDate = originalFormat.parse(date);
902 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss'Z'");
903 System.out.println(newFormat.format(toDate));