2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017 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 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.onap.aai.sparky.util;
25 import java.io.BufferedReader;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.lang.Thread.UncaughtExceptionHandler;
31 import java.nio.ByteBuffer;
32 import java.security.SecureRandom;
33 import java.sql.Timestamp;
34 import java.text.ParseException;
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.Date;
41 import java.util.Iterator;
42 import java.util.List;
44 import java.util.TimeZone;
45 import java.util.concurrent.ExecutorService;
46 import java.util.concurrent.Executors;
47 import java.util.concurrent.ThreadFactory;
48 import java.util.concurrent.TimeUnit;
49 import java.util.regex.Matcher;
50 import java.util.regex.Pattern;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.xml.stream.XMLStreamConstants;
55 import org.onap.aai.cl.api.Logger;
56 import org.onap.aai.sparky.logging.AaiUiMsgs;
57 import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
58 import org.restlet.Request;
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.fasterxml.jackson.databind.ser.FilterProvider;
66 import com.google.common.util.concurrent.ThreadFactoryBuilder;
70 * The Class NodeUtils.
72 public class NodeUtils {
73 private static SecureRandom sRandom = new SecureRandom();
75 private static final Pattern AAI_VERSION_PREFIX = Pattern.compile("/aai/v[0-9]+/(.*)");
78 public static synchronized String getRandomTxnId() {
79 byte bytes[] = new byte[6];
80 sRandom.nextBytes(bytes);
81 return Integer.toUnsignedString(ByteBuffer.wrap(bytes).getInt());
85 * Builds the depth padding.
87 * @param depth the depth
90 public static String buildDepthPadding(int depth) {
91 StringBuilder sb = new StringBuilder(32);
93 for (int x = 0; x < depth; x++) {
101 public static String extractRawPathWithoutVersion(String selfLinkUri) {
105 String rawPath = new URI(selfLinkUri).getRawPath();
107 Matcher m = AAI_VERSION_PREFIX.matcher(rawPath);
111 // System.out.println(m.group(0));
112 if (m.groupCount() >= 1) {
115 // System.out.println(m.group(2));
118 } catch (Exception e) {
126 * Checks if is numeric.
128 * @param numberStr the number str
129 * @return true, if is numeric
131 public static boolean isNumeric(String numberStr) {
134 Double.parseDouble(numberStr);
135 } catch (Exception exc) {
144 * Creates the named executor.
146 * @param name the name
147 * @param numWorkers the num workers
148 * @param logger the logger
149 * @return the executor service
151 public static ExecutorService createNamedExecutor(String name, int numWorkers,
152 final Logger logger) {
153 UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
156 public void uncaughtException(Thread thread, Throwable exc) {
158 logger.error(AaiUiMsgs.ERROR_GENERIC, thread.getName() + ": " + exc);
163 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(name + "-%d")
164 .setUncaughtExceptionHandler(uncaughtExceptionHandler).build();
166 return Executors.newScheduledThreadPool(numWorkers + 1, namedThreadFactory);
170 * Calculate edit attribute uri.
172 * @param link the link
175 public static String calculateEditAttributeUri(String link) {
180 Pattern pattern = Pattern.compile(TierSupportUiConstants.URI_VERSION_REGEX_PATTERN);
181 Matcher matcher = pattern.matcher(link);
182 if (matcher.find()) {
183 uri = link.substring(matcher.end());
190 * Generate unique sha digest.
192 * @param keys the keys
195 public static String generateUniqueShaDigest(String... keys) {
197 if ((keys == null) || keys.length == 0) {
201 final String keysStr = Arrays.asList(keys).toString();
202 final String hashedId = org.apache.commons.codec.digest.DigestUtils.sha256Hex(keysStr);
208 * Gets the node field as text.
210 * @param node the node
211 * @param fieldName the field name
212 * @return the node field as text
214 public static String getNodeFieldAsText(JsonNode node, String fieldName) {
216 String fieldValue = null;
218 JsonNode valueNode = node.get(fieldName);
220 if (valueNode != null) {
221 fieldValue = valueNode.asText();
227 private static final String ENTITY_RESOURCE_KEY_FORMAT = "%s.%s";
230 * Convert a millisecond duration to a string format
232 * @param millis A duration to convert to a string form
233 * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
236 private static final String TIME_BREAK_DOWN_FORMAT =
237 "[ %d days, %d hours, %d minutes, %d seconds ]";
240 * Gets the duration breakdown.
242 * @param millis the millis
243 * @return the duration breakdown
245 public static String getDurationBreakdown(long millis) {
248 return String.format(TIME_BREAK_DOWN_FORMAT, 0, 0, 0, 0);
251 long days = TimeUnit.MILLISECONDS.toDays(millis);
252 millis -= TimeUnit.DAYS.toMillis(days);
253 long hours = TimeUnit.MILLISECONDS.toHours(millis);
254 millis -= TimeUnit.HOURS.toMillis(hours);
255 long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
256 millis -= TimeUnit.MINUTES.toMillis(minutes);
257 long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
259 return String.format(TIME_BREAK_DOWN_FORMAT, days, hours, minutes, seconds);
264 * Checks if is equal.
268 * @return true, if is equal
270 public static boolean isEqual(JsonNode n1, JsonNode n2) {
273 * due to the inherent nature of json being unordered, comparing object representations of the
274 * same keys and values but different order makes comparison challenging. Let's try an
275 * experiment where we compare the structure of the json, and then simply compare the sorted
276 * order of that structure which should be good enough for what we are trying to accomplish.
279 TreeWalker walker = new TreeWalker();
280 List<String> n1Paths = new ArrayList<String>();
281 List<String> n2Paths = new ArrayList<String>();
283 walker.walkTree(n1Paths, n1);
284 walker.walkTree(n2Paths, n2);
286 Collections.sort(n1Paths);
287 Collections.sort(n2Paths);
289 return n1Paths.equals(n2Paths);
296 * @param list the list
299 public static String concatArray(List<String> list) {
300 return concatArray(list, " ");
303 private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
305 public static String getCurrentTimeStamp() {
306 SimpleDateFormat dateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
307 Timestamp timestamp = new Timestamp(System.currentTimeMillis());
308 return dateFormat.format(timestamp);
314 * @param list the list
315 * @param delimiter the delimiter
318 public static String concatArray(List<String> list, String delimiter) {
320 if (list == null || list.size() == 0) {
324 StringBuilder result = new StringBuilder(64);
326 boolean firstValue = true;
328 for (String item : list) {
334 result.append(delimiter).append(item);
339 return result.toString();
346 * @param values the values
349 public static String concatArray(String[] values) {
351 if (values == null || values.length == 0) {
355 StringBuilder result = new StringBuilder(64);
357 boolean firstValue = true;
359 for (String item : values) {
365 result.append(".").append(item);
370 return result.toString();
375 * Builds the entity resource key.
377 * @param entityType the entity type
378 * @param resourceId the resource id
381 public static String buildEntityResourceKey(String entityType, String resourceId) {
382 return String.format(ENTITY_RESOURCE_KEY_FORMAT, entityType, resourceId);
386 * Extract resource id from link.
388 * @param link the link
391 public static String extractResourceIdFromLink(String link) {
397 int linkLength = link.length();
398 if (linkLength == 0) {
403 * if the last character != / then we need to change the lastIndex position
407 String resourceId = null;
408 if ("/".equals(link.substring(linkLength - 1))) {
410 // https://aai-ext1.test.att.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS/
411 startIndex = link.lastIndexOf("/", linkLength - 2);
412 resourceId = link.substring(startIndex + 1, linkLength - 1);
415 // https://aai-ext1.test.att.com:9292/aai/v7/business/customers/customer/1607_20160524Func_Ak1_01/service-subscriptions/service-subscription/uCPE-VMS
416 startIndex = link.lastIndexOf("/");
417 resourceId = link.substring(startIndex + 1, linkLength);
420 String result = null;
422 if (resourceId != null) {
424 result = java.net.URLDecoder.decode(resourceId, "UTF-8");
425 } catch (Exception exc) {
427 * if there is a failure decoding the parameter we will just return the original value.
438 * Gets the xml stream constant as str.
440 * @param value the value
441 * @return the xml stream constant as str
443 public static String getXmlStreamConstantAsStr(int value) {
445 case XMLStreamConstants.ATTRIBUTE:
447 case XMLStreamConstants.CDATA:
449 case XMLStreamConstants.CHARACTERS:
451 case XMLStreamConstants.COMMENT:
453 case XMLStreamConstants.DTD:
455 case XMLStreamConstants.END_DOCUMENT:
456 return "END_DOCUMENT";
457 case XMLStreamConstants.END_ELEMENT:
458 return "END_ELEMENT";
459 case XMLStreamConstants.ENTITY_DECLARATION:
460 return "ENTITY_DECLARATION";
461 case XMLStreamConstants.ENTITY_REFERENCE:
462 return "ENTITY_REFERENCE";
463 case XMLStreamConstants.NAMESPACE:
465 case XMLStreamConstants.NOTATION_DECLARATION:
466 return "NOTATION_DECLARATION";
467 case XMLStreamConstants.PROCESSING_INSTRUCTION:
468 return "PROCESSING_INSTRUCTION";
469 case XMLStreamConstants.SPACE:
471 case XMLStreamConstants.START_DOCUMENT:
472 return "START_DOCUMENT";
473 case XMLStreamConstants.START_ELEMENT:
474 return "START_ELEMENT";
477 return "Unknown(" + value + ")";
482 * Convert object to json.
484 * @param object the object
485 * @param pretty the pretty
487 * @throws JsonProcessingException the json processing exception
489 public static String convertObjectToJson(Object object, boolean pretty)
490 throws JsonProcessingException {
491 ObjectWriter ow = null;
493 ObjectMapper mapper = new ObjectMapper();
494 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
497 ow = mapper.writer().withDefaultPrettyPrinter();
500 ow = mapper.writer();
503 return ow.writeValueAsString(object);
507 * Convert object to json by selectively choosing certain fields thru filters. Example use case:
508 * based on request type we might need to send different serialization of the UiViewFilterEntity
510 * @param object the object
511 * @param pretty the pretty
513 * @throws JsonProcessingException the json processing exception
515 public static String convertObjectToJson(Object object, boolean pretty, FilterProvider filters)
516 throws JsonProcessingException {
517 ObjectWriter ow = null;
519 ObjectMapper mapper = new ObjectMapper();
520 mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
523 ow = mapper.writer(filters).withDefaultPrettyPrinter();
526 ow = mapper.writer(filters);
529 return ow.writeValueAsString(object);
534 * Convert json str to json node.
536 * @param jsonStr the json str
537 * @return the json node
538 * @throws IOException Signals that an I/O exception has occurred.
540 public static JsonNode convertJsonStrToJsonNode(String jsonStr) throws IOException {
541 ObjectMapper mapper = new ObjectMapper();
542 if (jsonStr == null || jsonStr.length() == 0) {
546 return mapper.readTree(jsonStr);
550 * Convert object to xml.
552 * @param object the object
554 * @throws JsonProcessingException the json processing exception
556 public static String convertObjectToXml(Object object) throws JsonProcessingException {
557 ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
558 String jsonOutput = ow.writeValueAsString(object);
560 if (jsonOutput == null) {
564 return JsonXmlConverter.convertJsontoXml(jsonOutput);
569 * Extract objects by key.
571 * @param node the node
572 * @param searchKey the search key
573 * @param foundObjects the found objects
575 public static void extractObjectsByKey(JsonNode node, String searchKey,
576 Collection<JsonNode> foundObjects) {
582 if (node.isObject()) {
583 Iterator<Map.Entry<String, JsonNode>> nodeIterator = node.fields();
585 while (nodeIterator.hasNext()) {
586 Map.Entry<String, JsonNode> entry = nodeIterator.next();
587 if (!entry.getValue().isValueNode()) {
588 extractObjectsByKey(entry.getValue(), searchKey, foundObjects);
591 String name = entry.getKey();
592 if (name.equalsIgnoreCase(searchKey)) {
594 JsonNode entryNode = entry.getValue();
596 if (entryNode.isArray()) {
598 Iterator<JsonNode> arrayItemsIterator = entryNode.elements();
599 while (arrayItemsIterator.hasNext()) {
600 foundObjects.add(arrayItemsIterator.next());
604 foundObjects.add(entry.getValue());
610 } else if (node.isArray()) {
611 Iterator<JsonNode> arrayItemsIterator = node.elements();
612 while (arrayItemsIterator.hasNext()) {
613 extractObjectsByKey(arrayItemsIterator.next(), searchKey, foundObjects);
621 * Convert array into list.
623 * @param node the node
624 * @param instances the instances
626 public static void convertArrayIntoList(JsonNode node, Collection<JsonNode> instances) {
628 if (node.isArray()) {
629 Iterator<JsonNode> arrayItemsIterator = node.elements();
630 while (arrayItemsIterator.hasNext()) {
631 instances.add(arrayItemsIterator.next());
641 * Extract field values from object.
643 * @param node the node
644 * @param attributesToExtract the attributes to extract
645 * @param fieldValues the field values
647 public static void extractFieldValuesFromObject(JsonNode node,
648 Collection<String> attributesToExtract, Collection<String> fieldValues) {
654 if (node.isObject()) {
656 JsonNode valueNode = null;
658 for (String attrToExtract : attributesToExtract) {
660 valueNode = node.get(attrToExtract);
662 if (valueNode != null) {
664 if (valueNode.isValueNode()) {
665 fieldValues.add(valueNode.asText());
673 * Extract field value from object.
675 * @param node the node
676 * @param fieldName the field name
679 public static String extractFieldValueFromObject(JsonNode node, String fieldName) {
685 if (node.isObject()) {
687 JsonNode valueNode = node.get(fieldName);
689 if (valueNode != null) {
691 if (valueNode.isValueNode()) {
692 return valueNode.asText();
704 * @param timestamp the timestamp
707 public static String formatTimestamp(String timestamp) {
709 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
710 originalFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
711 Date toDate = originalFormat.parse(timestamp);
712 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
713 newFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
714 return newFormat.format(toDate);
716 } catch (ParseException pe) {
722 * Gets the HttpRequest payload.
724 * @param request the request
726 * @throws IOException Signals that an I/O exception has occurred.
728 public static String getBody(HttpServletRequest request) throws IOException {
729 InputStream inputStream = request.getInputStream();
730 return getBodyFromStream(inputStream);
736 * Gets the Restlet Request payload.
738 * @param request the request
740 * @throws IOException Signals that an I/O exception has occurred.
742 public static String getBody(Request request) throws IOException {
743 InputStream inputStream = request.getEntity().getStream();
744 return getBodyFromStream(inputStream);
749 * Gets the payload from the input stream of a request.
751 * @param request the request
753 * @throws IOException Signals that an I/O exception has occurred.
755 public static String getBodyFromStream(InputStream inputStream) throws IOException {
758 StringBuilder stringBuilder = new StringBuilder();
759 BufferedReader bufferedReader = null;
762 if (inputStream != null) {
763 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
764 char[] charBuffer = new char[128];
766 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
767 stringBuilder.append(charBuffer, 0, bytesRead);
770 stringBuilder.append("");
772 } catch (IOException ex) {
775 if (bufferedReader != null) {
777 bufferedReader.close();
778 } catch (IOException ex) {
784 body = stringBuilder.toString();
792 * @param args the arguments
793 * @throws ParseException the parse exception
795 public static void main(String[] args) throws ParseException {
796 String date = "20170110T112312Z";
797 SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd'T'hhmmss'Z'");
798 Date toDate = originalFormat.parse(date);
799 SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss'Z'");
800 System.out.println(newFormat.format(toDate));