2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
25 package org.onap.aai.sparky.util;
27 import java.io.BufferedReader;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.lang.Thread.UncaughtExceptionHandler;
33 import java.nio.ByteBuffer;
34 import java.security.SecureRandom;
35 import java.sql.Timestamp;
36 import java.text.ParseException;
37 import java.text.SimpleDateFormat;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.Date;
43 import java.util.Iterator;
44 import java.util.List;
46 import java.util.TimeZone;
47 import java.util.concurrent.ExecutorService;
48 import java.util.concurrent.Executors;
49 import java.util.concurrent.ThreadFactory;
50 import java.util.concurrent.TimeUnit;
51 import java.util.regex.Matcher;
52 import java.util.regex.Pattern;
54 import javax.servlet.http.HttpServletRequest;
55 import javax.xml.stream.XMLStreamConstants;
57 import org.onap.aai.cl.api.Logger;
58 import org.onap.aai.sparky.logging.AaiUiMsgs;
59 import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
60 import org.restlet.Request;
62 import com.fasterxml.jackson.core.JsonProcessingException;
63 import com.fasterxml.jackson.databind.JsonNode;
64 import com.fasterxml.jackson.databind.ObjectMapper;
65 import com.fasterxml.jackson.databind.ObjectWriter;
66 import com.fasterxml.jackson.databind.SerializationFeature;
67 import com.fasterxml.jackson.databind.ser.FilterProvider;
68 import com.google.common.util.concurrent.ThreadFactoryBuilder;
72 * The Class NodeUtils.
74 public class NodeUtils {
75 private static SecureRandom sRandom = new SecureRandom();
77 private static final Pattern AAI_VERSION_PREFIX = Pattern.compile("/aai/v[0-9]+/(.*)");
78 private static final Pattern GIZMO_VERSION_PREFIX = Pattern.compile("[/]*services/inventory/v[0-9]+/(.*)");
79 private static final Pattern GIZMO_RELATIONSHIP_VERSION_PREFIX = Pattern.compile("services/inventory/relationships/v[0-9]+/(.*)");
82 public static synchronized String getRandomTxnId(){
83 byte bytes[] = new byte[6];
84 sRandom.nextBytes(bytes);
85 return Integer.toUnsignedString(ByteBuffer.wrap(bytes).getInt());
89 * Builds the depth padding.
91 * @param depth the depth
94 public static String buildDepthPadding(int depth) {
95 StringBuilder sb = new StringBuilder(32);
97 for (int x = 0; x < depth; x++) {
101 return sb.toString();
105 public static String extractRawPathWithoutVersion(String selfLinkUri) {
109 String rawPath = new URI(selfLinkUri).getRawPath();
111 Matcher m = AAI_VERSION_PREFIX.matcher(rawPath);
115 if ( m.groupCount() >= 1) {
120 } catch (Exception e) {
127 public static String extractRawGizmoPathWithoutVersion(String resourceLink) {
131 String rawPath = new URI(resourceLink).getRawPath();
133 Matcher m = GIZMO_VERSION_PREFIX.matcher(rawPath);
137 if ( m.groupCount() >= 1) {
142 } catch (Exception e) {
149 public static String extractRawGizmoRelationshipPathWithoutVersion(String resourceLink) {
153 String rawPath = new URI(resourceLink).getRawPath();
155 Matcher m = GIZMO_RELATIONSHIP_VERSION_PREFIX.matcher(rawPath);
159 if ( m.groupCount() >= 1) {
164 } catch (Exception e) {
175 * Checks if is numeric.
177 * @param numberStr the number str
178 * @return true, if is numeric
180 public static boolean isNumeric(String numberStr) {
183 Double.parseDouble(numberStr);
184 } catch (Exception exc) {
193 * Creates the named executor.
195 * @param name the name
196 * @param numWorkers the num workers
197 * @param logger the logger
198 * @return the executor service
200 public static ExecutorService createNamedExecutor(String name, int numWorkers, final Logger logger) {
201 UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
204 public void uncaughtException(Thread thread, Throwable exc) {
206 logger.error(AaiUiMsgs.ERROR_GENERIC, thread.getName() + ": " + exc);
211 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(name + "-%d")
212 .setUncaughtExceptionHandler(uncaughtExceptionHandler).build();
214 return Executors.newScheduledThreadPool(numWorkers + 1, namedThreadFactory);
218 public static String calculateEditAttributeUri(String link) {
223 Pattern pattern = Pattern.compile(SparkyConstants.URI_VERSION_REGEX_PATTERN);
224 Matcher matcher = pattern.matcher(link);
225 if (matcher.find()) {
226 uri = link.substring(matcher.end());
234 * Generate unique sha digest.
236 * @param keys the keys
239 public static String generateUniqueShaDigest(String... keys) {
241 if ((keys == null) || keys.length == 0) {
245 final String keysStr = Arrays.asList(keys).toString();
246 final String hashedId = org.apache.commons.codec.digest.DigestUtils.sha256Hex(keysStr);
252 * Gets the node field as text.
254 * @param node the node
255 * @param fieldName the field name
256 * @return the node field as text
258 public static String getNodeFieldAsText(JsonNode node, String fieldName) {
260 String fieldValue = null;
262 JsonNode valueNode = node.get(fieldName);
264 if (valueNode != null) {
265 fieldValue = valueNode.asText();
271 private static final String ENTITY_RESOURCE_KEY_FORMAT = "%s.%s";
274 * Convert a millisecond duration to a string format
276 * @param millis A duration to convert to a string form
277 * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
280 private static final String TIME_BREAK_DOWN_FORMAT =
281 "[ %d days, %d hours, %d minutes, %d seconds ]";
284 * Gets the duration breakdown.
286 * @param millis the millis
287 * @return the duration breakdown
289 public static String getDurationBreakdown(long millis) {
292 return String.format(TIME_BREAK_DOWN_FORMAT, 0, 0, 0, 0);
295 long days = TimeUnit.MILLISECONDS.toDays(millis);
296 millis -= TimeUnit.DAYS.toMillis(days);
297 long hours = TimeUnit.MILLISECONDS.toHours(millis);
298 millis -= TimeUnit.HOURS.toMillis(hours);
299 long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
300 millis -= TimeUnit.MINUTES.toMillis(minutes);
301 long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
303 return String.format(TIME_BREAK_DOWN_FORMAT, days, hours, minutes, seconds);
308 * Checks if is equal.
312 * @return true, if is equal
314 public static boolean isEqual(JsonNode n1, JsonNode n2) {
317 * due to the inherent nature of json being unordered, comparing object representations of the
318 * same keys and values but different order makes comparison challenging. Let's try an
319 * experiment where we compare the structure of the json, and then simply compare the sorted
320 * order of that structure which should be good enough for what we are trying to accomplish.
323 TreeWalker walker = new TreeWalker();
324 List<String> n1Paths = new ArrayList<String>();
325 List<String> n2Paths = new ArrayList<String>();
327 walker.walkTree(n1Paths, n1);
328 walker.walkTree(n2Paths, n2);
330 Collections.sort(n1Paths);
331 Collections.sort(n2Paths);
333 return n1Paths.equals(n2Paths);
340 * @param list the list
343 public static String concatArray(List<String> list) {
344 return concatArray(list, " ");
347 private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
349 public static String getCurrentTimeStamp() {
350 SimpleDateFormat dateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
351 Timestamp timestamp = new Timestamp(System.currentTimeMillis());
352 return dateFormat.format(timestamp);
358 * @param list the list
359 * @param delimiter the delimiter
362 public static String concatArray(List<String> list, String delimiter) {
364 if (list == null || list.size() == 0) {
368 StringBuilder result = new StringBuilder(64);
370 boolean firstValue = true;
372 for (String item : list) {
378 result.append(delimiter).append(item);
383 return result.toString();
390 * @param values the values
393 public static String concatArray(String[] values) {
395 if (values == null || values.length == 0) {
399 StringBuilder result = new StringBuilder(64);
401 boolean firstValue = true;
403 for (String item : values) {
409 result.append(".").append(item);
414 return result.toString();
419 * Builds the entity resource key.
421 * @param entityType the entity type
422 * @param resourceId the resource id
425 public static String buildEntityResourceKey(String entityType, String resourceId) {
426 return String.format(ENTITY_RESOURCE_KEY_FORMAT, entityType, resourceId);
430 * Extract resource id from link.
432 * @param link the link
435 public static String extractResourceIdFromLink(String link) {
441 int linkLength = link.length();
442 if (linkLength == 0) {
447 * if the last character != / then we need to change the lastIndex position
451 String resourceId = null;
452 if ("/".equals(link.substring(linkLength - 1))) {
454 // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1/
455 startIndex = link.lastIndexOf("/", linkLength - 2);
456 resourceId = link.substring(startIndex + 1, linkLength - 1);
459 // https://ext1.test.onap.com:9292/aai/v7/business/customers/customer/customer-1/service-subscriptions/service-subscription/service-subscription-1
460 startIndex = link.lastIndexOf("/");
461 resourceId = link.substring(startIndex + 1, linkLength);
464 String result = null;
466 if (resourceId != null) {
468 result = java.net.URLDecoder.decode(resourceId, "UTF-8");
469 } catch (Exception exc) {
471 * if there is a failure decoding the parameter we will just return the original value.
482 * Gets the xml stream constant as str.
484 * @param value the value
485 * @return the xml stream constant as str
487 public static String getXmlStreamConstantAsStr(int value) {
489 case XMLStreamConstants.ATTRIBUTE:
491 case XMLStreamConstants.CDATA:
493 case XMLStreamConstants.CHARACTERS:
495 case XMLStreamConstants.COMMENT:
497 case XMLStreamConstants.DTD:
499 case XMLStreamConstants.END_DOCUMENT:
500 return "END_DOCUMENT";
501 case XMLStreamConstants.END_ELEMENT:
502 return "END_ELEMENT";
503 case XMLStreamConstants.ENTITY_DECLARATION:
504 return "ENTITY_DECLARATION";
505 case XMLStreamConstants.ENTITY_REFERENCE:
506 return "ENTITY_REFERENCE";
507 case XMLStreamConstants.NAMESPACE:
509 case XMLStreamConstants.NOTATION_DECLARATION:
510 return "NOTATION_DECLARATION";
511 case XMLStreamConstants.PROCESSING_INSTRUCTION:
512 return "PROCESSING_INSTRUCTION";
513 case XMLStreamConstants.SPACE:
515 case XMLStreamConstants.START_DOCUMENT:
516 return "START_DOCUMENT";
517 case XMLStreamConstants.START_ELEMENT:
518 return "START_ELEMENT";
521 return "Unknown(" + value + ")";
526 * Convert object to json.
528 * @param object the object
529 * @param pretty the pretty
531 * @throws JsonProcessingException the json processing exception
533 public static String convertObjectToJson(Object object, boolean pretty)
534 throws JsonProcessingException {
535 ObjectWriter ow = null;
537 ObjectMapper mapper = new ObjectMapper();
538 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
541 ow = mapper.writer().withDefaultPrettyPrinter();
544 ow = mapper.writer();
547 return ow.writeValueAsString(object);
551 * Convert object to json by selectively choosing certain fields thru filters.
553 * based on request type we might need to send different serialization of the UiViewFilterEntity
555 * @param object the object
556 * @param pretty the pretty
558 * @throws JsonProcessingException the json processing exception
560 public static String convertObjectToJson(Object object, boolean pretty, FilterProvider filters)
561 throws JsonProcessingException {
562 ObjectWriter ow = null;
564 ObjectMapper mapper = new ObjectMapper();
565 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
568 ow = mapper.writer(filters).withDefaultPrettyPrinter();
571 ow = mapper.writer(filters);
574 return ow.writeValueAsString(object);
579 * Convert json str to json node.
581 * @param jsonStr the json str
582 * @return the json node
583 * @throws IOException Signals that an I/O exception has occurred.
585 public static JsonNode convertJsonStrToJsonNode(String jsonStr) throws IOException {
586 ObjectMapper mapper = new ObjectMapper();
587 if (jsonStr == null || jsonStr.length() == 0) {
591 return mapper.readTree(jsonStr);
595 * Convert object to xml.
597 * @param object the object
599 * @throws JsonProcessingException the json processing exception
601 public static String convertObjectToXml(Object object) throws JsonProcessingException {
602 ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
603 String jsonOutput = ow.writeValueAsString(object);
605 if (jsonOutput == null) {
609 return JsonXmlConverter.convertJsontoXml(jsonOutput);
614 * Extract objects by key.
616 * @param node the node
617 * @param searchKey the search key
618 * @param foundObjects the found objects
620 public static void extractObjectsByKey(JsonNode node, String searchKey,
621 Collection<JsonNode> foundObjects) {
623 if ( node == null ) {
627 if (node.isObject()) {
628 Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
630 while (nodeIterator.hasNext()) {
631 Map.Entry<String, JsonNode> entry = nodeIterator.next();
632 if (!entry.getValue().isValueNode()) {
633 extractObjectsByKey(entry.getValue(), searchKey, foundObjects);
636 String name = entry.getKey();
637 if (name.equalsIgnoreCase(searchKey)) {
639 JsonNode entryNode = entry.getValue();
641 if (entryNode.isArray()) {
643 Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
644 while (arrayItemsIterator.hasNext()) {
645 foundObjects.add(arrayItemsIterator.next());
649 foundObjects.add(entry.getValue());
655 } else if (node.isArray()) {
656 Iterator<JsonNode> arrayItemsIterator = node.elements();
657 while (arrayItemsIterator.hasNext()) {
658 extractObjectsByKey(arrayItemsIterator.next(), searchKey, foundObjects);
664 public static String extractObjectValueByKey(JsonNode node, String searchKey) {
670 if (node.isObject()) {
671 Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
673 while (nodeIterator.hasNext()) {
674 Map.Entry<String, JsonNode> entry = nodeIterator.next();
675 if (!entry.getValue().isValueNode()) {
676 return extractObjectValueByKey(entry.getValue(), searchKey);
679 String name = entry.getKey();
680 if (name.equalsIgnoreCase(searchKey)) {
682 JsonNode entryNode = entry.getValue();
684 if (entryNode.isArray()) {
686 Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
687 while (arrayItemsIterator.hasNext()) {
688 return arrayItemsIterator.next().asText();
692 return entry.getValue().asText();
698 } else if (node.isArray()) {
699 Iterator<JsonNode> arrayItemsIterator = node.elements();
700 while (arrayItemsIterator.hasNext()) {
701 return extractObjectValueByKey(arrayItemsIterator.next(), searchKey);
711 * Convert array into list.
713 * @param node the node
714 * @param instances the instances
716 public static void convertArrayIntoList(JsonNode node, Collection<JsonNode> instances) {
718 if (node.isArray()) {
719 Iterator<JsonNode> arrayItemsIterator = node.elements();
720 while (arrayItemsIterator.hasNext()) {
721 instances.add(arrayItemsIterator.next());
731 * Extract field values from object.
733 * @param node the node
734 * @param attributesToExtract the attributes to extract
735 * @param fieldValues the field values
737 public static void extractFieldValuesFromObject(JsonNode node,
738 Collection<String> attributesToExtract, Collection<String> fieldValues) {
744 if (node.isObject()) {
746 JsonNode valueNode = null;
748 for (String attrToExtract : attributesToExtract) {
750 valueNode = node.get(attrToExtract);
752 if (valueNode != null) {
754 if (valueNode.isValueNode()) {
755 fieldValues.add(valueNode.asText());
763 * Extract field value from object.
765 * @param node the node
766 * @param fieldName the field name
769 public static String extractFieldValueFromObject(JsonNode node, String fieldName) {
775 if (node.isObject()) {
777 JsonNode valueNode = node.get(fieldName);
779 if (valueNode != null) {
781 if (valueNode.isValueNode()) {
782 return valueNode.asText();
794 * @param timestamp the timestamp
797 public static String formatTimestamp(String timestamp) {
799 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
800 originalFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
801 Date toDate = originalFormat.parse(timestamp);
802 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
803 newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
804 return newFormat.format(toDate);
806 } catch (ParseException pe) {
812 * Gets the HttpRequest payload.
814 * @param request the request
816 * @throws IOException Signals that an I/O exception has occurred.
818 public static String getBody(HttpServletRequest request) throws IOException {
819 InputStream inputStream = request.getInputStream();
820 return getBodyFromStream(inputStream);
826 * Gets the Restlet Request payload.
828 * @param request the request
830 * @throws IOException Signals that an I/O exception has occurred.
832 public static String getBody(Request request) throws IOException {
833 InputStream inputStream = request.getEntity().getStream();
834 return getBodyFromStream(inputStream);
839 * Gets the payload from the input stream of a request.
841 * @param request the request
843 * @throws IOException Signals that an I/O exception has occurred.
845 public static String getBodyFromStream(InputStream inputStream) throws IOException {
848 StringBuilder stringBuilder = new StringBuilder();
849 BufferedReader bufferedReader = null;
852 if (inputStream != null) {
853 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
854 char[] charBuffer = new char[128];
856 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
857 stringBuilder.append(charBuffer, 0, bytesRead);
860 stringBuilder.append("");
862 } catch (IOException ex) {
865 if (bufferedReader != null) {
867 bufferedReader.close();
868 } catch (IOException ex) {
874 body = stringBuilder.toString();
882 * @param args the arguments
883 * @throws ParseException the parse exception
885 public static void main(String[] args) throws ParseException {
886 String date = "20170110T112312Z";
887 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'hhmmss'Z'");
888 Date toDate = originalFormat.parse(date);
889 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss'Z'");
890 System.out.println(newFormat.format(toDate));