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