AT&T 1712 and 1802 release code
[so.git] / bpmn / MSOCoreBPMN / src / main / java / org / openecomp / mso / bpmn / core / json / JsonUtils.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP - SO\r
4  * ================================================================================\r
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.\r
7  * ================================================================================\r
8  * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * you may not use this file except in compliance with the License.\r
10  * You may obtain a copy of the License at\r
11  * \r
12  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * \r
14  * Unless required by applicable law or agreed to in writing, software\r
15  * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * See the License for the specific language governing permissions and\r
18  * limitations under the License.\r
19  * ============LICENSE_END=========================================================\r
20  */\r
21 \r
22 package org.openecomp.mso.bpmn.core.json;\r
23 \r
24 import java.io.IOException;\r
25 import java.util.ArrayList;\r
26 import java.util.HashMap;\r
27 import java.util.Iterator;\r
28 import java.util.List;\r
29 import java.util.Map;\r
30 import java.util.StringTokenizer;\r
31 \r
32 import org.camunda.bpm.engine.delegate.DelegateExecution;\r
33 import org.camunda.bpm.engine.runtime.Execution;\r
34 import org.json.JSONArray;\r
35 import org.json.JSONException;\r
36 import org.json.JSONObject;\r
37 import org.json.XML;\r
38 import org.openecomp.mso.apihandler.common.ValidationException;\r
39 //import org.openecomp.mso.bpmn.core.BPMNLogger;\r
40 import org.openecomp.mso.bpmn.core.xml.XmlTool;\r
41 import org.openecomp.mso.logger.MsoLogger;\r
42 \r
43 import com.fasterxml.jackson.databind.JsonNode;\r
44 import com.github.fge.jackson.JsonLoader;\r
45 import com.github.fge.jsonschema.core.exceptions.ProcessingException;\r
46 import com.github.fge.jsonschema.core.report.ProcessingReport;\r
47 import com.github.fge.jsonschema.main.JsonSchemaFactory;\r
48 import com.github.fge.jsonschema.main.JsonValidator;\r
49 \r
50 /**\r
51  * Utility class for JSON processing\r
52  * \r
53  * @version 1.0\r
54  * \r
55  * Note: It was observed, that depending on the JSON implementation, an org.json.JSONException or a\r
56  *       java.util.NoSuchElementException will be thrown in the event of the key value being "not found"\r
57  *       in a JSON document. A general check has been added to the applicable catch blocks for this\r
58  *       this type of behavior to reduce the amount of logging. As a key value not being found is\r
59  *       expect behavior, it makes no sense to log the stack trace associated with this type of failure.\r
60  */\r
61 \r
62 public class JsonUtils {\r
63 \r
64         private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);\r
65         private static int MSOJsonIndentFactor = 3;\r
66 \r
67         /**\r
68          * Uses the JSONObject static method to convert a XML doc to JSON.\r
69          *\r
70          * @param  xml          String containing the XML doc\r
71          * @param  pretty       flag to determine if the output should be formatted\r
72          * @return String containing the JSON translation\r
73          */\r
74         public static String xml2json(String xml, Boolean pretty) {\r
75 //              String isDebugLogEnabled = "true";\r
76                 try {\r
77                         // name spaces cause problems, so just remove them\r
78                         JSONObject jsonObj = XML.toJSONObject(XmlTool.removeNamespaces(xml));\r
79                         if (!pretty) {\r
80                                 return jsonObj.toString();\r
81                         } else {\r
82                                 // add an indent to make it 'pretty'\r
83                                 return jsonObj.toString(MSOJsonIndentFactor);\r
84                         }\r
85                 } catch (Exception e){\r
86                                 msoLogger.debug("xml2json(): unable to parse xml and convert to json. Exception was: " + e.toString(), e);\r
87                                 return null;\r
88                 }\r
89         }\r
90 \r
91         /**\r
92          * Invokes xml2json(String, Boolean) defaulting to 'pretty' output.\r
93          *\r
94          * @param  xml  String containing the XML doc\r
95          * @return String containing the JSON translation\r
96          */\r
97         public static String xml2json(String xml) {\r
98                 return xml2json(xml, true);\r
99         }\r
100 \r
101         /**\r
102          * Uses the JSONObject static method to convert a JSON doc to XML.\r
103          * Note: this method may not generate valid XML if the JSONObject\r
104          * contains JSONArrays which are used to represent XML attributes\r
105          * in the JSON doc.\r
106          *\r
107          * @param  jsonStr      String containing the JSON doc\r
108          * @param  pretty       flag to determine if the output should be formatted\r
109          * @return String containing the XML translation\r
110          */\r
111         public static String json2xml(String jsonStr, Boolean pretty) {\r
112 //              String isDebugLogEnabled = "true";\r
113                 try {\r
114                         JSONObject jsonObj = new JSONObject(jsonStr);\r
115                         if (pretty) {\r
116 //                              return XmlTool.normalize(XML.toString(jsonObj));\r
117 //                              use the local class method which properly handles certain JSONArray content\r
118                                 return XmlTool.normalize(toXMLString(jsonObj, null));\r
119                         } else {\r
120 //                              return XML.toString(jsonObj);\r
121 //                              use the local class method which properly handles certain JSONArray content\r
122                                 return toXMLString(jsonObj, null);\r
123                         }\r
124                 } catch (Exception e){\r
125                                 msoLogger.debug("json2xml(): unable to parse json and convert to xml. Exception was: " + e.toString(), e);\r
126                                 return null;\r
127                 }\r
128         }\r
129 \r
130         /**\r
131          * Uses a modified version of the org.json.XML toString() algorithm\r
132          * to convert a JSONObject to an XML Doc. The intent of this is to\r
133          * correctly generate XML from JSON including TAGs for JSONArrays\r
134          *\r
135          * @param  obj  org.json.JSON object to be converted to XML\r
136          * @param  tagName      optional XML tagname supplied primarily during recursive calls\r
137          * @return String containing the XML translation\r
138          */\r
139         public static String toXMLString(Object obj, String tagName) throws JSONException {\r
140                 StringBuilder strBuf = new StringBuilder();\r
141                 int i;\r
142                 JSONArray jsonArr;\r
143                 JSONObject jsonObj;\r
144                 String key;\r
145                 Iterator<String> keys;\r
146                 int len;\r
147                 String str;\r
148                 Object curObj;\r
149                 if (obj instanceof JSONObject) {\r
150                         // msoLogger.debug("toXMLString(): is a JSONObject");\r
151                         // append "<tagName>" to the XML output\r
152                         if (tagName != null) {\r
153 //                              msoLogger.debug("toXMLString(): adding opening tagName: " + tagName);\r
154                                 strBuf.append("<");\r
155                                 strBuf.append(tagName);\r
156                                 strBuf.append(">");\r
157                         }\r
158                         // iterate thru the keys.\r
159                         jsonObj = (JSONObject) obj;\r
160                         keys = jsonObj.keys();\r
161                         while (keys.hasNext()) {\r
162                                 key = keys.next();\r
163                                 // msoLogger.debug("toXMLString(): key is " + k);\r
164                                 curObj = jsonObj.opt(key);\r
165                                 if (curObj == null) {\r
166                                         curObj = "";\r
167                                 }\r
168                                 if (curObj instanceof String) {\r
169                                         str = (String) curObj;\r
170                                 } else {\r
171                                         str = null;\r
172                                 }\r
173                                 // append the content to the XML output\r
174                                 if ("content".equals(key)) {\r
175                                         if (curObj instanceof JSONArray) {\r
176                                                 jsonArr = (JSONArray) curObj;\r
177                                                 len = jsonArr.length();\r
178                                                 for (i = 0; i < len; i += 1) {\r
179                                                         if (i > 0) {\r
180                                                                 strBuf.append('\n');\r
181                                                         }\r
182                                                         strBuf.append(XML.escape(jsonArr.get(i).toString()));\r
183                                                 }\r
184                                         } else {\r
185                                                 strBuf.append(XML.escape(curObj.toString()));\r
186                                         }\r
187                                 // append an array of similar keys to the XML output\r
188                                 } else if (curObj instanceof JSONArray) {\r
189                                         jsonArr = (JSONArray) curObj;\r
190                                         len = jsonArr.length();\r
191 //                                      msoLogger.debug("toXMLString(): found JSONArray: " + key + ", size: " + len);\r
192                                         for (i = 0; i < len; i += 1) {\r
193                                                 curObj = jsonArr.get(i);\r
194                                                 if (curObj instanceof JSONArray) {\r
195 //                                                      The XML tags for the nested array should be generated below when this method\r
196 //                                                      is called recursively and the JSONArray object is passed\r
197 //                                                      strBuf.append("<");\r
198 //                                                      strBuf.append(key);\r
199 //                                                      strBuf.append(">");\r
200                                                         strBuf.append(toXMLString(curObj, null));\r
201 //                                                      strBuf.append("</");\r
202 //                                                      strBuf.append(key);\r
203 //                                                      strBuf.append(">");\r
204                                                 } else {\r
205 //                                                      msoLogger.debug("toXMLString(): recursive call toXML() with tagName null");\r
206                                                         // append the opening tag for the array (before 1st element)\r
207                                                         if (i == 0) {\r
208                                                                 strBuf.append("<");\r
209                                                                 strBuf.append(key);\r
210                                                                 strBuf.append(">");\r
211                                                         }\r
212                                                         // append the opening tag for the array\r
213                                                         strBuf.append(toXMLString(curObj, null));\r
214                                                         // append the closing tag for the array (after last element)\r
215                                                         if (i == (len - 1)) {\r
216                                                                 strBuf.append("</");\r
217                                                                 strBuf.append(key);\r
218                                                                 strBuf.append(">");\r
219                                                         }\r
220                                                 }\r
221                                         }\r
222                                 } else if (curObj.equals("")) {\r
223                                         // append a closing tag "<key>" to the XML output\r
224                                         strBuf.append("<");\r
225                                         strBuf.append(key);\r
226                                         strBuf.append("/>");\r
227                                 } else {\r
228 //                                      msoLogger.debug("toXMLString(): recursive call toXMLString() with tagName: " + key);\r
229                                         strBuf.append(toXMLString(curObj, key));\r
230                                 }\r
231                                 // msoLogger.debug("toXML(): partial XML: " + strBuf.toString());\r
232                         }\r
233                         if (tagName != null) {\r
234                                 // append the closing tag "</tagName>" to the XML output\r
235 //                              msoLogger.debug("toXMLString(): adding closing tagName: " + tagName);\r
236                                 strBuf.append("</");\r
237                                 strBuf.append(tagName);\r
238                                 strBuf.append(">");\r
239                         }\r
240                         return strBuf.toString();\r
241                 // XML does not have good support for arrays. If an array appears in a place\r
242                 // where XML is lacking, synthesize an < array > element.\r
243                 } else if (obj instanceof JSONArray) {\r
244                         jsonArr = (JSONArray) obj;\r
245                         len = jsonArr.length();\r
246                         for (i = 0; i < len; ++i) {\r
247                                 curObj = jsonArr.opt(i);\r
248                                 strBuf.append(toXMLString(curObj, (tagName == null) ? "array"\r
249                                                 : tagName));\r
250                         }\r
251                         return strBuf.toString();\r
252                 } else {\r
253 //                      msoLogger.debug("toXML(): in else block with tagName: " + tagName);\r
254                         str = (obj == null) ? "null" : XML.escape(obj.toString());\r
255                         return (tagName == null) ? "\"" + str + "\""\r
256                                         : (str.length() == 0) ? "<" + tagName + "/>" : "<"\r
257                                                         + tagName + ">" + str + "</" + tagName + ">";\r
258                 }\r
259         }\r
260 \r
261         /**\r
262          * Invokes json2xml(String, Boolean) defaulting to 'pretty' output.\r
263          *\r
264          * @param  jsonStr      String containing the XML doc\r
265          * @return String containing the JSON translation\r
266          */\r
267         public static String json2xml(String jsonStr) {\r
268                 return json2xml(jsonStr, true);\r
269         }\r
270 \r
271         /**\r
272          * Formats the JSON String using the value of MSOJsonIndentFactor.\r
273          *\r
274          * @param  jsonStr      String containing the JSON doc\r
275          * @return String containing the formatted JSON doc\r
276          */\r
277         public static String prettyJson(String jsonStr) {\r
278 //              String isDebugLogEnabled = "true";\r
279                 try {\r
280                         JSONObject jsonObj = new JSONObject(jsonStr);\r
281                         return jsonObj.toString(MSOJsonIndentFactor);\r
282                 } catch (Exception e){\r
283                         msoLogger.debug("prettyJson(): unable to parse/format json input. Exception was: " + e.toString(), e);\r
284                         return null;\r
285                 }\r
286         }\r
287 \r
288         /**\r
289          * Returns an Iterator over the JSON keys in the specified JSON doc.\r
290          *\r
291          * @param  jsonStr      String containing the JSON doc\r
292          * @return Iterator over the JSON keys\r
293          * @throws JSONException if the doc cannot be parsed\r
294          */\r
295         public static Iterator <String> getJsonIterator(String jsonStr) throws JSONException {\r
296                 return new JSONObject(jsonStr).keys();\r
297         }\r
298 \r
299         /**\r
300          * Returns the name of the "root" property in the specified JSON doc. The\r
301          * "root" property is the single top-level property in the JSON doc. An\r
302          * exception is thrown if the doc is empty or if it contains more than one\r
303          * top-level property.\r
304          *\r
305          * @param  jsonStr      String containing the JSON doc\r
306          * @return the name of the "root" property\r
307          * @throws JSONException if the doc cannot be parsed, or if it is empty, or if\r
308          *         it contains more than one top-level property\r
309          */\r
310         public static String getJsonRootProperty(String jsonStr) throws JSONException {\r
311                 Iterator<String> iter = getJsonIterator(jsonStr);\r
312 \r
313                 if (!iter.hasNext()) {\r
314                         throw new JSONException("Empty JSON object");\r
315                 }\r
316 \r
317                 String rootPropertyName = iter.next();\r
318 \r
319                 if (iter.hasNext()) {\r
320                         throw new JSONException("JSON object has more than one root property");\r
321                 }\r
322 \r
323                 return rootPropertyName;\r
324         }\r
325 \r
326         /**\r
327          * Invokes the getJsonRawValue() method and returns the String equivalent of\r
328          * the object returned.\r
329          *\r
330          * TBD: May need separate methods for boolean, float, and integer fields if the\r
331          * String representation is not sufficient to meet client needs.\r
332          *\r
333          * @param  jsonStr      String containing the JSON doc\r
334          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
335          * @return String field value associated with keys\r
336          */\r
337         public static String getJsonValue(String jsonStr, String keys) {\r
338 //              String isDebugLogEnabled = "true";\r
339                 try {\r
340                                 Object rawValue = getJsonRawValue(jsonStr, keys);\r
341                                 if (rawValue == null) {\r
342                                         return null;\r
343                                 } else {\r
344                                         if (rawValue instanceof String) {\r
345                                                 msoLogger.debug("getJsonValue(): the raw value is a String Object=" + rawValue);\r
346                                                 return (String) rawValue;\r
347                                         } else {\r
348                                                 msoLogger.debug("getJsonValue(): the raw value is NOT a String Object=" + rawValue.toString());\r
349                                                 return rawValue.toString();\r
350                                         }\r
351                                 }\r
352                 } catch (Exception e) {\r
353                                 msoLogger.debug("getJsonValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);\r
354                 }\r
355                 return null;\r
356         }\r
357 \r
358         /**\r
359          * Invokes the getJsonRawValue() method with the wrap flag set to true\r
360          * and returns the String equivalent of the json node object returned.\r
361          *\r
362          * @param  jsonStr      String containing the JSON doc\r
363          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
364          * @return String field value associated with keys\r
365          */\r
366         public static String getJsonNodeValue(String jsonStr, String keys) {\r
367 //              String isDebugLogEnabled = "true";\r
368                 try {\r
369                                 Object rawValue = getJsonRawValue(jsonStr, keys, true);\r
370                                 if (rawValue == null) {\r
371                                         return null;\r
372                                 } else {\r
373                                         if (rawValue instanceof String) {\r
374                                                 msoLogger.debug("getJsonNodeValue(): the raw value is a String Object=" + rawValue);\r
375                                                 return (String) rawValue;\r
376                                         } else {\r
377                                                 msoLogger.debug("getJsonNodeValue(): the raw value is NOT a String Object=" + rawValue.toString());\r
378                                                 return rawValue.toString();\r
379                                         }\r
380                                 }\r
381                 } catch (Exception e) {\r
382                                 msoLogger.debug("getJsonNodeValue(): unable to parse json to retrieve node for field=" + keys + ". Exception was: " + e.toString(), e);\r
383                 }\r
384                 return null;\r
385         }\r
386 \r
387         /**\r
388          * Invokes the getJsonRawValue() method and returns the String equivalent of\r
389          * the object returned.\r
390          *\r
391          * TBD: May need separate methods for boolean, float, and integer fields if the\r
392          * String representation is not sufficient to meet client needs.\r
393          *\r
394          * @param  jsonStr      String containing the JSON doc\r
395          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
396          * @return String field value associated with keys\r
397          */\r
398         public static int getJsonIntValue(String jsonStr, String keys) {\r
399 //              String isDebugLogEnabled = "true";\r
400                 try {\r
401                                 Object rawValue = getJsonRawValue(jsonStr, keys);\r
402                                 if (rawValue == null) {\r
403                                         return 0;\r
404                                 } else {\r
405                                         if (rawValue instanceof Integer) {\r
406                                                 msoLogger.debug("getJsonValue(): the raw value is an Integer Object=" + rawValue);\r
407                                                 return (Integer) rawValue;\r
408                                         } else {\r
409                                                 msoLogger.debug("getJsonIntValue(): the raw value is NOT an Integer Object=" + rawValue.toString());\r
410                                                 return 0;\r
411                                         }\r
412                                 }\r
413                 } catch (Exception e) {\r
414                                 msoLogger.debug("getJsonIntValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(), e);\r
415                 }\r
416                 return 0;\r
417         }\r
418 \r
419         /**\r
420          * Invokes the getJsonRawValue() method and returns the boolean equivalent of\r
421          * the object returned.\r
422          *\r
423          * @param  jsonStr      String containing the JSON doc\r
424          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
425          * @return boolean field value associated with keys - default is false\r
426          */\r
427         public static boolean getJsonBooleanValue(String jsonStr, String keys) {\r
428                 try {\r
429                                 Object rawValue = getJsonRawValue(jsonStr, keys);\r
430                                 if (rawValue == null) {\r
431                                         return false;\r
432                                 } else {\r
433                                         if (rawValue instanceof Boolean) {\r
434                                                 msoLogger.debug("getJsonBooleanValue(): the raw value is a Boolean Object=" + rawValue);\r
435                                                 return (Boolean) rawValue;\r
436                                         } else {\r
437                                                 msoLogger.debug("getJsonBooleanValue(): the raw value is NOT an Boolean Object=" + rawValue.toString());\r
438                                                 return false;\r
439                                         }\r
440                                 }\r
441                 } catch (Exception e) {\r
442                                 msoLogger.debug("getJsonBooleanValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);\r
443                 }\r
444                 return false;\r
445         }\r
446 \r
447         /**\r
448          * Invokes the getJsonParamValue() method to obtain the JSONArray associated with\r
449          * the specified keys. The JSONArray is then walked to retrieve the first array\r
450          * value associated with the specified field name (index=0).\r
451          *\r
452          * @param  jsonStr      String containing the JSON doc\r
453          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
454          * @param  name         field name for the param to be retrieved\r
455          * @return String param value associated with field name\r
456          */\r
457         public static String getJsonParamValue(String jsonStr, String keys, String name) {\r
458                 return getJsonParamValue(jsonStr, keys, name, 0);\r
459         }\r
460 \r
461         /**\r
462          * Invokes the getJsonRawValue() method to obtain the JSONArray associated with\r
463          * the specified keys. The JSONArray is then walked to retrieve the nth array\r
464          * value associated with the specified field name and index.\r
465          *\r
466          * @param  jsonStr      String containing the JSON doc\r
467          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
468          * @param  name         field name for the param to be retrieved\r
469          * @param  index    the nth param associated with name starting at 0\r
470          * @return String param value associated with field name\r
471          */\r
472         public static String getJsonParamValue(String jsonStr, String keys, String name, int index) {\r
473 //              String isDebugLogEnabled = "true";\r
474                 try {\r
475                         Object rawValue = getJsonRawValue(jsonStr, keys);\r
476                         if (rawValue == null) {\r
477                                 return null;\r
478                         } else {\r
479                                 if (rawValue instanceof JSONArray) {\r
480                                         msoLogger.debug("getJsonParamValue(): keys=" + keys + " points to JSONArray: " + rawValue.toString());\r
481                                         int arrayLen = ((JSONArray) rawValue).length();\r
482                                         if (index < 0 || arrayLen < index+1) {\r
483                                                 msoLogger.debug("getJsonParamValue(): index: " + index + " is out of bounds for array size of " + arrayLen);\r
484                                                 return null;\r
485                                         }\r
486                                         int foundCnt = 0;\r
487                                         for (int i = 0; i < arrayLen; i++) {\r
488                                                 msoLogger.debug("getJsonParamValue(): index: " + i + ", value: " + ((JSONArray) rawValue).get(i).toString());\r
489                                                 if (((JSONArray) rawValue).get(i) instanceof JSONObject) {\r
490 //                                                      msoLogger.debug("getJsonParamValue(): index: " + i + " is a JSONObject");\r
491                                                         JSONObject jsonObj = (JSONObject)((JSONArray) rawValue).get(i);\r
492                                                         String parmValue = jsonObj.get(name).toString();\r
493                                                         if (parmValue != null) {\r
494                                                                 msoLogger.debug("getJsonParamValue(): found value: " + parmValue + " for name: " + name + " and index: " + i);\r
495                                                                 if (foundCnt == index) {\r
496                                                                         return parmValue;\r
497                                                                 } else {\r
498                                                                         foundCnt++;\r
499                                                                         continue;\r
500                                                                 }\r
501                                                         } else {\r
502                                                                 continue;\r
503                                                         }\r
504                                                 } else {\r
505                                                         msoLogger.debug("getJsonParamValue(): the JSONArray element is NOT a JSONObject=" + rawValue.toString());\r
506                                                         return null;\r
507                                                 }\r
508                                         }\r
509                                         msoLogger.debug("getJsonParamValue(): content value NOT found for name: " + name);\r
510                                         return null;\r
511                                 } else {\r
512                                         msoLogger.debug("getJsonParamValue(): the raw value is NOT a JSONArray Object=" + rawValue.toString());\r
513                                         return null;\r
514                                 }\r
515                         }\r
516                 } catch (Exception e) {\r
517                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
518                         if (e.getMessage().contains("not found")) {\r
519                                 msoLogger.debug("getJsonParamValue(): failed to retrieve param value for keys:" + keys + ", name=" + name + ": " + e.getMessage());                             \r
520                         } else {\r
521                                 msoLogger.debug("getJsonParamValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(), e);\r
522                         }\r
523                 }\r
524                 return null;\r
525         }\r
526 \r
527         /**\r
528          * Wrapper to generate the JSONObject to pass to the getJsonValueForKey(JSONObject, String)\r
529          * method so that recursion over the subobjects can be supported there\r
530          *\r
531          * @param  jsonStr      String containing the JSON doc\r
532          * @param  key          key to the target value\r
533          * @return String field value associated with key\r
534          */\r
535         public static String getJsonValueForKey(String jsonStr, String key) {\r
536 //              String isDebugLogEnabled = "true";\r
537                 try {\r
538                         JSONObject jsonObj = new JSONObject(jsonStr);\r
539                         return getJsonValueForKey(jsonObj, key);\r
540                 } catch (Exception e) {\r
541                                 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(), e);\r
542                 }\r
543                 return null;\r
544         }\r
545 \r
546         /**\r
547          * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the\r
548          * single key/field name specified. Returns the associated value if found or null if the key is not found\r
549          *\r
550          * @param  jsonObj      JSONObject representation of the the JSON doc\r
551          * @param  key          key to the target value\r
552          * @return String field value associated with key\r
553          */\r
554         public static String getJsonValueForKey(JSONObject jsonObj, String key) {\r
555 //              String isDebugLogEnabled = "true";\r
556                 String keyValue = null;\r
557                 try {\r
558                         if (jsonObj.has(key)) {\r
559                                 Object value = jsonObj.get(key);\r
560                                 msoLogger.debug("getJsonValueForKey(): found value=" + (String) value + ", for key=" + key);\r
561                                 if (value == null) {\r
562                                         return null;\r
563                                 } else {\r
564                                         return ((String) value);\r
565                                 }\r
566                         } else {\r
567 //                              msoLogger.debug("getJsonValueForKey(): iterating over the keys");\r
568                                 Iterator <String> itr = jsonObj.keys();\r
569                                 while (itr.hasNext()) {\r
570                                         String nextKey = itr.next();\r
571                                         Object obj = jsonObj.get(nextKey);\r
572                                         if (obj instanceof JSONObject) {\r
573 //                                              msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call on: " +\r
574 //                                                              ((JSONObject) obj).toString(MSOJsonIndentFactor));\r
575                                                 keyValue = getJsonValueForKey((JSONObject) obj, key);\r
576                                                 if (keyValue != null) {\r
577 //                                                      msoLogger.debug("getJsonValueForKey(): found value=" + keyValue + ", for key=" + key);\r
578                                                         break;\r
579                                                 }\r
580                                         } else {\r
581                                                 msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");\r
582                                         }\r
583                                 }\r
584                         }\r
585                 } catch (Exception e) {\r
586                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
587                         if (e.getMessage().contains("not found")) {\r
588                                 msoLogger.debug("getJsonValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());                         \r
589                         } else {\r
590                                 msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(), e);\r
591                         }\r
592                         keyValue = null;\r
593                 }\r
594                 return keyValue;\r
595         }\r
596 \r
597         /**\r
598          * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the\r
599          * single key/field name specified. Returns the associated value if found or null if the key is not found\r
600          *\r
601          * @param  jsonObj      JSONObject representation of the the JSON doc\r
602          * @param  key          key to the target value\r
603          * @return String field value associated with key\r
604          */\r
605         public static Integer getJsonIntValueForKey(JSONObject jsonObj, String key) {\r
606 //              String isDebugLogEnabled = "true";\r
607                 Integer keyValue = null;\r
608                 try {\r
609                         if (jsonObj.has(key)) {\r
610                                 Integer value = (Integer) jsonObj.get(key);\r
611                                 msoLogger.debug("getJsonIntValueForKey(): found value=" + value + ", for key=" + key);\r
612                                 return value;\r
613                         } else {\r
614 //                              msoLogger.debug("getJsonIntValueForKey(): iterating over the keys");\r
615                                 Iterator <String> itr = jsonObj.keys();\r
616                                 while (itr.hasNext()) {\r
617                                         String nextKey = itr.next();\r
618                                         Object obj = jsonObj.get(nextKey);\r
619                                         if (obj instanceof JSONObject) {\r
620 //                                              msoLogger.debug("getJsonIntValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");\r
621                                                 keyValue = getJsonIntValueForKey((JSONObject) obj, key);\r
622                                                 if (keyValue != null) {\r
623 //                                                      msoLogger.debug("getJsonIntValueForKey(): found value=" + keyValue + ", for key=" + key);\r
624                                                         break;\r
625                                                 }\r
626                                         } else {\r
627                                                 msoLogger.debug("getJsonIntValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");\r
628                                         }\r
629                                 }\r
630                         }\r
631                 } catch (Exception e) {\r
632                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
633                         if (e.getMessage().contains("not found")) {\r
634                                 msoLogger.debug("getJsonIntValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());                              \r
635                         } else {\r
636                                 msoLogger.debug("getJsonIntValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(),e);\r
637                         }\r
638                         keyValue = null;\r
639                 }\r
640                 return keyValue;\r
641         }\r
642 \r
643         /**\r
644          * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the\r
645          * single key/field name specified. Returns the associated value if found or null if the key is not found\r
646          *\r
647          * @param  jsonObj      JSONObject representation of the the JSON doc\r
648          * @param  key          key to the target value\r
649          * @return String field value associated with key\r
650          */\r
651         public static Boolean getJsonBooleanValueForKey(JSONObject jsonObj, String key) {\r
652                 Boolean keyValue = null;\r
653                 try {\r
654                         if (jsonObj.has(key)) {\r
655                                 Boolean value = (Boolean) jsonObj.get(key);\r
656                                 msoLogger.debug("getJsonBooleanValueForKey(): found value=" + value + ", for key=" + key);                              \r
657                                 return value;\r
658                         } else {\r
659 //                              msoLogger.debug("getJsonBooleanValueForKey(): iterating over the keys");\r
660                                 Iterator <String> itr = jsonObj.keys();\r
661                                 while (itr.hasNext()) {\r
662                                         String nextKey = itr.next();\r
663                                         Object obj = jsonObj.get(nextKey);\r
664                                         if (obj instanceof JSONObject) {\r
665 //                                              msoLogger.debug("getJsonBooleanValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");\r
666                                                 keyValue = getJsonBooleanValueForKey((JSONObject) obj, key);\r
667                                                 if (keyValue != null) {\r
668 //                                                      msoLogger.debug("getJsonBooleanValueForKey(): found value=" + keyValue + ", for key=" + key);\r
669                                                         break;\r
670                                                 }\r
671                                         } else {\r
672                                                 msoLogger.debug("getJsonBooleanValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");\r
673                                         }\r
674                                 }\r
675                         }\r
676                 } catch (Exception e) {\r
677                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
678                         if (e.getMessage().contains("not found")) {\r
679                                 msoLogger.debug("getJsonBooleanValueForKey(): failed to retrieve param value for key=" + key + ": " + e.getMessage());                          \r
680                         } else {\r
681                                 msoLogger.debug("getJsonBooleanValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString(),e);\r
682                         }\r
683                         keyValue = null;\r
684                 }\r
685                 return keyValue;\r
686         }\r
687 \r
688         /**\r
689          * Boolean method to determine if a key path is valid for the JSON doc. Invokes\r
690          * getJsonValue().\r
691          *\r
692          * @param  jsonStr      String containing the JSON doc\r
693          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
694          * @return Boolean true if keys points to value in the JSON doc\r
695          */\r
696         public static Boolean jsonValueExists(String jsonStr, String keys) {\r
697                 if (getJsonRawValue(jsonStr, keys) == null) {\r
698                         return false;\r
699                 } else {\r
700                         return true;\r
701                 }\r
702         }\r
703 \r
704         /**\r
705          * Inserts the new key/value pair at the appropriate location in the JSON\r
706          * document after first determining if keyed field already exists. If\r
707          * it does exist, return the JSON unmodified, otherwise return the new JSON\r
708          * Note: this method currently only supports String value inserts.\r
709          *\r
710          * @param  jsonStr      String containing the JSON doc\r
711          * @param  keys         full key path to the value to be added in the format of "key1.key2.key3..."\r
712          * @return String containing the updated JSON doc\r
713          */\r
714         public static String addJsonValue(String jsonStr, String keys, String value) {\r
715 //              String isDebugLogEnabled = "true";\r
716                 // only attempt to insert the key/value pair if it does not exist\r
717                 if (!jsonValueExists(jsonStr, keys)) {\r
718                         return putJsonValue(jsonStr, keys, value);\r
719                 } else {\r
720                         msoLogger.debug("addJsonValue(): JSON add failed, key=" + keys + "/value=" + value + " already exists");\r
721                         return jsonStr;\r
722                 }\r
723         }\r
724 \r
725         /**\r
726          * Updates the value for the specified key in the JSON document\r
727          * after first determining if keyed field exists. If it does\r
728          * not exist, return the JSON unmodified, otherwise return the updated JSON.\r
729          * Note: this method currently only supports String value updates.\r
730          *\r
731          * @param  jsonStr      String containing the JSON doc\r
732          * @param  keys         full key path to the value to be updated in the format of "key1.key2.key3..."\r
733          * @return String containing the updated JSON doc\r
734          */\r
735         public static String updJsonValue(String jsonStr, String keys, String newValue) {\r
736 //              String isDebugLogEnabled = "true";\r
737                 // only attempt to modify the key/value pair if it exists\r
738                 if (jsonValueExists(jsonStr, keys)) {\r
739                         return putJsonValue(jsonStr, keys, newValue);\r
740                 } else {\r
741                         msoLogger.debug("updJsonValue(): JSON update failed, no value exists for key=" + keys);\r
742                         return jsonStr;\r
743                 }\r
744         }\r
745 \r
746         /**\r
747          * Deletes the value for the specified key in the JSON document\r
748          * after first determining if keyed field exists. If it does\r
749          * not exist, return the JSON unmodified, otherwise return the updated JSON\r
750          *\r
751          * @param  jsonStr      String containing the JSON doc\r
752          * @param  keys         full key path to the value to be deleted in the format of "key1.key2.key3..."\r
753          * @return String containing the updated JSON doc\r
754          */\r
755         public static String delJsonValue(String jsonStr, String keys) {\r
756 //              String isDebugLogEnabled = "true";\r
757                 // only attempt to remove the key/value pair if it exists\r
758                 if (jsonValueExists(jsonStr, keys)) {\r
759                         // passing a null value results in a delete\r
760                         return putJsonValue(jsonStr, keys, null);\r
761                 } else {\r
762                         msoLogger.debug("delJsonValue(): JSON delete failed, no value exists for key=" + keys);\r
763                         return jsonStr;\r
764                 }\r
765         }\r
766 \r
767         /**\r
768          * Walks the JSON doc using the full key path to retrieve the associated\r
769          * value. All but the last key points to the 'parent' object name(s) in order\r
770          * in the JSON hierarchy with the last key pointing to the target value.\r
771          * The value returned is a Java object.\r
772          *\r
773          * @param  jsonStr      String containing the JSON doc\r
774          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
775          * @return Object field value associated with keys\r
776          */\r
777         private static Object getJsonRawValue(String jsonStr, String keys) {\r
778                 return getJsonRawValue(jsonStr, keys, false);\r
779         }\r
780 \r
781         /**\r
782          * Walks the JSON doc using the full key path to retrieve the associated\r
783          * value. All but the last key points to the 'parent' object name(s) in order\r
784          * in the JSON hierarchy with the last key pointing to the target value.\r
785          * The value returned is a Java object.\r
786          *\r
787          * @param  jsonStr      String containing the JSON doc\r
788          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
789          * @param  wrap         Boolean which determines if returned JSONObjects sould be "wrapped"\r
790          *                  Note: wrap does not apply to returned scalar values\r
791          * @return Object field value associated with keys\r
792          */\r
793         private static Object getJsonRawValue(String jsonStr, String keys, Boolean wrap) {\r
794 //              String isDebugLogEnabled = "true";\r
795                 String keyStr = "";\r
796                 try {\r
797                         JSONObject jsonObj = new JSONObject(jsonStr);\r
798                         StringTokenizer keyTokens = new StringTokenizer(keys, ".");\r
799                         while (keyTokens.hasMoreElements()) {\r
800                                 keyStr = keyTokens.nextToken();\r
801                                 Object keyValue = jsonObj.get(keyStr);\r
802                                 if (keyValue instanceof JSONObject) {\r
803 //                                      msoLogger.debug("getJsonRawValue(): key=" + keyStr + " points to json object");\r
804                                         jsonObj = (JSONObject) keyValue;\r
805                                 } else {\r
806                                         if (keyTokens.hasMoreElements()) {\r
807                                                 msoLogger.debug("getJsonRawValue(): value found prior to last key for key=" + keyStr);\r
808                                         }\r
809                                         return keyValue;\r
810                                 }\r
811                         }\r
812                         // return the json 'node' that the key points to\r
813                         // note: since this is a json object and not a scalar value,\r
814                         //       use the wrap flag to determine if the object should\r
815                         //       be wrapped with a root node value\r
816                         //       (the last key in the keys String)\r
817                         if (wrap) {\r
818                                 JSONObject wrappedJsonObj = new JSONObject();\r
819                                 wrappedJsonObj.put(keyStr, jsonObj);\r
820                                 return wrappedJsonObj.toString();\r
821                         } else {\r
822                                 return jsonObj.toString();\r
823                         }\r
824 \r
825                 } catch (Exception e) {\r
826                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
827                         if (e.getMessage().contains("not found")) {\r
828                                 msoLogger.debug("getJsonRawValue(): failed to retrieve param value for key=" + keyStr + ": " + e.getMessage());                         \r
829                         } else {\r
830                                 msoLogger.debug("getJsonRawValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString(),e);\r
831                         }\r
832                 }\r
833                 return null;\r
834         }\r
835 \r
836         /**\r
837          * Private method invoked by the public add, update, and delete methods.\r
838          *\r
839          * @param  jsonStr      String containing the JSON doc\r
840          * @param  keys         full key path to the value to be deleted in the format of "key1.key2.key3..."\r
841          * @return String containing the updated JSON doc\r
842          */\r
843         private static String putJsonValue(String jsonStr, String keys, String value) {\r
844 //              String isDebugLogEnabled = "true";\r
845                 String keyStr = "";\r
846                 try {\r
847                         JSONObject jsonObj = new JSONObject(jsonStr);\r
848                         JSONObject jsonObjOut = jsonObj;\r
849                         StringTokenizer keyTokens = new StringTokenizer(keys, ".");\r
850                         while (keyTokens.hasMoreElements()) {\r
851                                 keyStr = keyTokens.nextToken();\r
852                                 if (keyTokens.hasMoreElements()) {\r
853                                         Object keyValue = jsonObj.get(keyStr);\r
854                                         if (keyValue instanceof JSONObject) {\r
855 //                                              msoLogger.debug("putJsonValue(): key=" + keyStr + " points to json object");\r
856                                                 jsonObj = (JSONObject) keyValue;\r
857                                         } else {\r
858                                                 msoLogger.debug("putJsonValue(): key=" + keyStr + " not the last key but points to non-json object: " + keyValue);\r
859                                                 return null;\r
860                                         }\r
861                                 } else { // at the last/new key value\r
862                                         jsonObj.put(keyStr, value);\r
863                                         return jsonObjOut.toString(3);\r
864                                 }\r
865                         }\r
866                         // should not hit this point if the key points to a valid key value\r
867                         return null;\r
868 \r
869                 } catch (Exception e) {\r
870                         // JSONObject::get() throws a "not found" exception if one of the specified keys is not found\r
871                         if (e.getMessage().contains("not found")) {\r
872                                 msoLogger.debug("putJsonValue(): failed to put param value for key=" + keyStr + ": " + e.getMessage());                         \r
873                         } else {\r
874                                 msoLogger.debug("putJsonValue(): unable to parse json to put value for key=" + keys + ". Exception was: " + e.toString(),e);\r
875                         }\r
876                 }\r
877                 return null;\r
878         }\r
879 \r
880         /**\r
881          * This json util method converts a json array of Key Value\r
882          * pair objects into a Java Map.\r
883          *\r
884          * @param execution\r
885          * @param entryArray - the getJsonValue of a json Array of key/value pairs\r
886          *\r
887          * @return Map - a Map containing the entries\r
888          */\r
889         public Map<String, String> jsonStringToMap(DelegateExecution execution, String entry) {\r
890                 msoLogger.debug("Started Json String To Map Method");\r
891 \r
892                 Map<String, String> map = new HashMap<>();\r
893 \r
894                 //Populate Map\r
895                 JSONObject obj = new JSONObject(entry);\r
896                 \r
897                 /* Wildfly is pushing a version of org.json which does not\r
898                  * auto cast to string. Leaving it as an object prevents\r
899                  * a method not found exception at runtime.\r
900                  */\r
901                 final Iterator<String> keys = obj.keys();\r
902                 while (keys.hasNext()) {\r
903                         final String key = keys.next();\r
904                         map.put(key, obj.getString(key));\r
905                 }\r
906                 msoLogger.debug("Outgoing Map is: " + map);\r
907                 msoLogger.debug("Completed Json String To Map Method");\r
908                 return map;\r
909         }\r
910 \r
911         /**\r
912          * This json util method converts a json array of Key Value\r
913          * pair objects into a Java Map.\r
914          *\r
915          * @param execution\r
916          * @param entryArray - the getJsonValue of a json Array of key/value pairs\r
917          * @param keyNode - the name of the node that represents the key\r
918          * @param valueNode - the name of the node that represents the value\r
919          *\r
920          * @return Map - a Map containing the entries\r
921          *\r
922          */\r
923         public Map<String, String> entryArrayToMap(DelegateExecution execution, String entryArray, String keyNode, String valueNode) {\r
924                 msoLogger.debug("Started Entry Array To Map Util Method");\r
925 \r
926                 Map<String, String> map = new HashMap<>();\r
927                 //Populate Map\r
928                 String entryListJson = "{ \"wrapper\":" + entryArray + "}";\r
929                 JSONObject obj = new JSONObject(entryListJson);\r
930                 JSONArray arr = obj.getJSONArray("wrapper");\r
931                 for (int i = 0; i < arr.length(); i++){\r
932                         JSONObject jo = arr.getJSONObject(i);\r
933                         String key = jo.getString(keyNode);\r
934                         String value =jo.getString(valueNode);\r
935                         map.put(key, value);\r
936                 }\r
937                 msoLogger.debug("Outgoing Map is: " + map);\r
938                 msoLogger.debug("Completed Entry Array To Map Util Method");\r
939                 return map;\r
940         }\r
941 \r
942         /**\r
943          * This json util method converts a json Array of Strings\r
944          * to a Java List. It takes each String in the json Array\r
945          * and puts it in a Java List<String>.\r
946          *\r
947          * @param execution\r
948          * @param jsonArrayOfStrings - the getJsonValue of a json array of strings\r
949          *\r
950          * @return List - a java list containing the strings\r
951          *\r
952          *\r
953          */\r
954         public List<String> StringArrayToList(Execution execution, String jsonArrayOfStrings) {\r
955                 msoLogger.debug("Started  String Array To List Util Method");\r
956 \r
957                 List<String> list = new ArrayList<>();\r
958                 //Populate List\r
959                 String stringListJson = "{ \"strings\":" + jsonArrayOfStrings + "}";\r
960                 JSONObject obj = new JSONObject(stringListJson);\r
961                 JSONArray arr = obj.getJSONArray("strings");\r
962                 for (int i = 0; i < arr.length(); i++){\r
963                         String s = arr.get(i).toString();\r
964                         list.add(s);\r
965                 }\r
966                 msoLogger.debug("Outgoing List is: " + list);\r
967                 msoLogger.debug("Completed String Array To List Util Method");\r
968                 return list;\r
969         }\r
970 \r
971         /**\r
972          *\r
973          * Invokes the getJsonRawValue() method to determine if the\r
974          * json element/variable exist. Returns true if the\r
975          * json element exist\r
976          *\r
977          * @param  jsonStr      String containing the JSON doc\r
978          * @param  keys         full key path to the target value in the format of "key1.key2.key3..."\r
979          * @return boolean field value associated with keys\r
980          *\r
981          *\r
982          */\r
983         public static boolean jsonElementExist(String jsonStr, String keys) {\r
984 \r
985                 try {\r
986                         Object rawValue = getJsonRawValue(jsonStr, keys);\r
987 \r
988                         return !(rawValue == null);\r
989 \r
990                 } catch (Exception e) {\r
991                                 msoLogger.debug("jsonElementExist(): unable to determine if json element exist. Exception is: " + e.toString(),e);\r
992                 }\r
993                 return true;\r
994         }\r
995 \r
996         /**\r
997          *\r
998          * Validates the JSON document against a schema file.\r
999          *\r
1000          * @param  jsonStr      String containing the JSON doc\r
1001          * @param  jsonSchemaPath full path to a valid JSON schema file\r
1002          * @return String the validation results/report\r
1003          *\r
1004          *\r
1005          */\r
1006     public static String jsonSchemaValidation(String jsonStr, String jsonSchemaPath) throws ValidationException {\r
1007         try {\r
1008                 msoLogger.debug("JSON document to be validated: " + jsonStr);\r
1009                 JsonNode document = JsonLoader.fromString(jsonStr);\r
1010 //              JsonNode document = JsonLoader.fromFile(jsonDoc);\r
1011                 JsonNode schema = JsonLoader.fromPath(jsonSchemaPath);\r
1012 \r
1013                 JsonSchemaFactory factory = JsonSchemaFactory.byDefault();\r
1014                 JsonValidator validator = factory.getValidator();\r
1015 \r
1016                 ProcessingReport report = validator.validate(schema, document);\r
1017                 msoLogger.debug("JSON schema validation report: " + report.toString());\r
1018                 return report.toString();\r
1019         } catch (IOException e) {\r
1020                 msoLogger.debug("IOException performing JSON schema validation on document: " + e.toString());\r
1021                 throw new ValidationException(e.getMessage());\r
1022         } catch (ProcessingException e) {\r
1023                 msoLogger.debug("ProcessingException performing JSON schema validation on document: " + e.toString());\r
1024                 throw new ValidationException(e.getMessage());\r
1025         }\r
1026     }\r
1027 }\r