Standalone TCA with EELF Logger
[dcaegen2/analytics/tca-gen2.git] / dcae-analytics / dcae-analytics-model / src / main / java / org / onap / dcae / analytics / model / util / function / JsonStringToMapFunction.java
1 /*
2  * ================================================================================
3  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ============LICENSE_END=========================================================
17  *
18  */
19
20 package org.onap.dcae.analytics.model.util.function;
21
22 import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.Map;
30 import java.util.function.Function;
31
32 import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Converts JSON String to flatten map of key value pair
38  *
39  * @author Rajiv Singla
40  */
41 public class JsonStringToMapFunction implements Function<String, Map<String, Object>> {
42
43     private static final Logger logger = LoggerFactory.getLogger(JsonStringToMapFunction.class);
44
45     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
46     private final String keyPrefix;
47     private final String keySeparator;
48
49     public JsonStringToMapFunction(final String keyPrefix, final String keySeparator) {
50         this.keyPrefix = keyPrefix;
51         this.keySeparator = keySeparator;
52     }
53
54     public JsonStringToMapFunction(final String keyPrefix) {
55         this(keyPrefix, ConfigBindingServiceConstants.KEY_SEPARATOR);
56     }
57
58     public JsonStringToMapFunction() {
59         this("", ConfigBindingServiceConstants.KEY_SEPARATOR);
60     }
61
62     @Override
63     @SuppressWarnings("unchecked")
64     public Map<String, Object> apply(final String jsonString) {
65
66         logger.debug("Converting JSON to flattened key value Map: {}", jsonString);
67         if (jsonString == null || jsonString.trim().isEmpty()) {
68             return new HashMap<>();
69         }
70
71         final Map<String, Object> result = flattenJson(jsonString);
72         logger.debug("Flattened Key Value Pairs");
73         result.forEach((key, value) -> logger.debug("{}:{}", key, value));
74         return result;
75     }
76
77     /**
78      * Flattens Json String
79      *
80      * @param jsonString json String
81      *
82      * @return map containing flattened json string key and value
83      */
84     private Map<String, Object> flattenJson(final String jsonString) {
85
86         try {
87             final JsonNode rootNode = OBJECT_MAPPER.readTree(jsonString);
88             final LinkedHashMap<String, Object> result = new LinkedHashMap<>();
89             flattenJsonNode(keyPrefix, rootNode, result);
90             return result;
91         } catch (IOException e) {
92             final String errorMessage = String.format("Unable to flatten JSON String to Map. Invalid JSON String: " +
93                     "%s", jsonString);
94             logger.error(errorMessage, e, jsonString);
95             throw new IllegalArgumentException(jsonString, e);
96         }
97
98     }
99
100     /**
101      * Flattens json array
102      *
103      * @param propertyPrefix property prefix
104      * @param jsonNodesIterator json array node that needs to be flattened
105      * @param resultMap result map containing flattened key value pairs
106      */
107     private void flattenJsonArray(String propertyPrefix, Iterator<JsonNode> jsonNodesIterator,
108                                   Map<String, Object> resultMap) {
109         int counter = 0;
110         while (jsonNodesIterator.hasNext()) {
111             flattenJsonNode(propertyPrefix + "[" + counter + "]", jsonNodesIterator.next(), resultMap);
112             counter++;
113         }
114
115     }
116
117     /**
118      * Flattens json array
119      *
120      * @param propertyPrefix property prefix
121      * @param objectNode json object node that needs to be flattened
122      * @param resultMap result map containing flattened key value pairs
123      */
124     private void flattenJsonMap(String propertyPrefix, JsonNode objectNode,
125                                 Map<String, Object> resultMap) {
126         final Iterator<Map.Entry<String, JsonNode>> fieldsIterator = objectNode.fields();
127         while (fieldsIterator.hasNext()) {
128             final Map.Entry<String, JsonNode> fieldEntry = fieldsIterator.next();
129             final JsonNode jsonValue = fieldEntry.getValue();
130             final String jsonKey = fieldEntry.getKey();
131             flattenJsonNode(
132                     (propertyPrefix.isEmpty() ? "" : propertyPrefix + keySeparator) + jsonKey,
133                     jsonValue, resultMap);
134         }
135     }
136
137     /**
138      * Checks various elements types of JSON Types and flattens them based on their type
139      *
140      * @param propertyPrefix property prefix
141      * @param currentJsonNode currentJsonNode that may need to be flattened
142      * @param resultMap result map containing flattened key value pairs
143      */
144     private void flattenJsonNode(final String propertyPrefix, final JsonNode currentJsonNode,
145                                  final Map<String, Object> resultMap) {
146
147
148         if (currentJsonNode.isObject()) {
149             flattenJsonMap(propertyPrefix, currentJsonNode, resultMap);
150         } else if (currentJsonNode.isArray()) {
151             flattenJsonArray(propertyPrefix, currentJsonNode.iterator(), resultMap);
152         } else {
153             resultMap.put(propertyPrefix, getObjectValue(currentJsonNode));
154         }
155     }
156
157     private static Object getObjectValue(final JsonNode jsonNode) {
158         if (jsonNode.isTextual()) {
159             return jsonNode.textValue();
160         } else if (jsonNode.isNumber()) {
161             return jsonNode.asLong();
162         } else if (jsonNode.isBoolean()) {
163             return jsonNode.asBoolean();
164         } else {
165             return jsonNode.asText();
166         }
167     }
168 }
169