[MSO-8] Update the maven dependency
[so.git] / bpmn / MSOCoreBPMN / src / main / java / org / openecomp / mso / bpmn / core / json / JsonUtils.java
index 8329746..462bda8 100644 (file)
 package org.openecomp.mso.bpmn.core.json;
 
 import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
 import java.util.StringTokenizer;
 
+import org.camunda.bpm.engine.runtime.Execution;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -79,7 +82,7 @@ public class JsonUtils {
 
        /**
         * Uses the JSONObject static method to convert a JSON doc to XML.
-        * Note: this method will not generate valid XML if the JSONObject
+        * Note: this method may not generate valid XML if the JSONObject
         * contains JSONArrays which are used to represent XML attributes
         * in the JSON doc.
         *
@@ -92,9 +95,11 @@ public class JsonUtils {
                try {
                        JSONObject jsonObj = new JSONObject(jsonStr);
                        if (pretty) {
-                               return XmlTool.normalize(XML.toString(jsonObj));
+                               //      use the local class method which properly handles certain JSONArray content
+                               return XmlTool.normalize(toXMLString(jsonObj, null));
                        } else {
-                               return XML.toString(jsonObj);
+//                             use the local class method which properly handles certain JSONArray content
+                               return toXMLString(jsonObj, null);
                        }
                } catch (Exception e){
                                msoLogger.debug("json2xml(): unable to parse json and convert to xml. Exception was: " + e.toString());
@@ -102,6 +107,154 @@ public class JsonUtils {
                }
        }
        
+       /**
+        * Uses a modified version of the org.json.XML toString() algorithm
+        * to convert a JSONObject to an XML Doc. The intent of this is to
+        * correctly generate XML from JSON including TAGs for JSONArrays
+        *
+        * @param  jsonObj      org.json.JSON object to be converted to XML
+        * @param  tagName      optional XML tagname supplied primarily during recursive calls
+        * @return String containing the XML translation
+        */
+       public static String toXMLString(Object obj, String tagName) throws JSONException {
+               StringBuffer strBuf = new StringBuffer();
+               int i;
+               JSONArray jsonArr;
+               JSONObject jsonObj;
+               String key;
+               Iterator<String> keys;
+               int len;
+               String str;
+               Object curObj;
+               if (obj instanceof JSONObject) {
+                       // msoLogger.debug("toXMLString(): is a JSONObject");
+                       // append "<tagName>" to the XML output
+                       if (tagName != null) {
+//                             msoLogger.debug("toXMLString(): adding opening tagName: " + tagName);
+                               strBuf.append("<");
+                               strBuf.append(tagName);
+                               strBuf.append(">");
+                       }
+                       // iterate thru the keys.
+                       jsonObj = (JSONObject) obj;
+                       keys = jsonObj.keys();
+                       while (keys.hasNext()) {
+                               key = keys.next().toString();
+                               // msoLogger.debug("toXMLString(): key is " + k);
+                               curObj = jsonObj.opt(key);
+                               if (curObj == null) {
+                                       curObj = "";
+                               }
+                               if (curObj instanceof String) {
+                                       str = (String) curObj;
+                               } else {
+                                       str = null;
+                               }
+                               // append the content to the XML output
+                               if (key.equals("content")) {
+                                       if (curObj instanceof JSONArray) {
+                                               jsonArr = (JSONArray) curObj;
+                                               len = jsonArr.length();
+                                               for (i = 0; i < len; i += 1) {
+                                                       if (i > 0) {
+                                                               strBuf.append('\n');
+                                                       }
+                                                       strBuf.append(XML.escape(jsonArr.get(i).toString()));
+                                               }
+                                       } else {
+                                               strBuf.append(XML.escape(curObj.toString()));
+                                       }
+                               // append an array of similar keys to the XML output
+                               } else if (curObj instanceof JSONArray) {
+                                       jsonArr = (JSONArray) curObj;
+                                       len = jsonArr.length();
+//                                     msoLogger.debug("toXMLString(): found JSONArray: " + key + ", size: " + len);
+                                       for (i = 0; i < len; i += 1) {
+                                               curObj = jsonArr.get(i);
+                                               if (curObj instanceof JSONArray) {
+//                                                     The XML tags for the nested array should be generated below when this method
+//                                                     is called recursively and the JSONArray object is passed                                                        
+//                                                     strBuf.append("<");
+//                                                     strBuf.append(key);
+//                                                     strBuf.append(">");
+                                                       strBuf.append(toXMLString(curObj, null));
+//                                                     strBuf.append("</");
+//                                                     strBuf.append(key);
+//                                                     strBuf.append(">");
+                                               } else {
+//                                                     msoLogger.debug("toXMLString(): recursive call toXML() with tagName null");
+                                                       // append the opening tag for the array (before 1st element)
+                                                       if (i == 0) {
+                                                               strBuf.append("<");
+                                                               strBuf.append(key);
+                                                               strBuf.append(">");
+                                                       }
+                                                       // append the opening tag for the array
+                                                       strBuf.append(toXMLString(curObj, null));
+                                                       // append the closing tag for the array (after last element)
+                                                       if (i == (len - 1)) {
+                                                               strBuf.append("</");
+                                                               strBuf.append(key);
+                                                               strBuf.append(">");
+                                                       }
+                                               }
+                                       }
+                               } else if (curObj.equals("")) {
+                                       // append a closing tag "<key>" to the XML output
+                                       strBuf.append("<");
+                                       strBuf.append(key);
+                                       strBuf.append("/>");
+                               } else {
+//                                     msoLogger.debug("toXMLString(): recursive call toXMLString() with tagName: " + key);
+                                       strBuf.append(toXMLString(curObj, key));
+                               }
+                               // msoLogger.debug("toXML(): partial XML: " + strBuf.toString());
+                       }
+                       if (tagName != null) {
+                               // append the closing tag "</tagName>" to the XML output
+//                             msoLogger.debug("toXMLString(): adding closing tagName: " + tagName);
+                               strBuf.append("</");
+                               strBuf.append(tagName);
+                               strBuf.append(">");
+                       }
+                       return strBuf.toString();
+               // XML does not have good support for arrays. If an array appears in a place
+               // where XML is lacking, synthesize an < array > element.
+               } else if (obj instanceof JSONArray) {
+                       jsonArr = (JSONArray) obj;
+                       len = jsonArr.length();
+                       for (i = 0; i < len; ++i) {
+                               curObj = jsonArr.opt(i);
+                               strBuf.append(toXMLString(curObj, (tagName == null) ? "array"
+                                               : tagName));
+                       }
+                       return strBuf.toString();
+               } else {
+//                     msoLogger.debug("toXML(): in else block with tagName: " + tagName);
+                       str = (obj == null) ? "null" : XML.escape(obj.toString());
+                       return (tagName == null) ? "\"" + str + "\""
+                                       : (str.length() == 0) ? "<" + tagName + "/>" : "<"
+                                                       + tagName + ">" + str + "</" + tagName + ">";
+               }
+       }
+       
+       /**
+        * Formats the JSON String using the value of MSOJsonIndentFactor.
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @return String containing the formatted JSON doc
+        */
+       public static String prettyJson(String jsonStr) {
+//             String isDebugLogEnabled = "true";
+               try {
+                       JSONObject jsonObj = new JSONObject(jsonStr);
+                       return jsonObj.toString(MSOJsonIndentFactor);
+               } catch (Exception e){
+                       msoLogger.debug("prettyJson(): unable to parse/format json input. Exception was: " + e.toString());
+                       return null;
+               }
+       }
+       
        /**
         * Invokes json2xml(String, Boolean) defaulting to 'pretty' output.
         *
@@ -111,23 +264,43 @@ public class JsonUtils {
        public static String json2xml(String jsonStr) {
                return json2xml(jsonStr, true);
        }
-
+       
        /**
-        * Uses the JSONObject static method to convert a JSON doc to XML.
+        * Returns an Iterator over the JSON keys in the specified JSON doc.
         *
         * @param  jsonStr      String containing the JSON doc
         * @return Iterator over the JSON keys
+        * @throws JSONException if the doc cannot be parsed
         */
-       public static Iterator <String> getJsonIterator(String jsonStr) {
-//             String isDebugLogEnabled = "true";
-               try {
-                       JSONObject json = new JSONObject(jsonStr);
-                       return json.keys();
-                       
-               } catch (Exception e){
-                               msoLogger.debug("getJsonIterator(): unable to parse json to retrieve the keys iterator. Exception was: " + e.toString());
-                               return null;
+       public static Iterator <String> getJsonIterator(String jsonStr) throws JSONException {
+               return new JSONObject(jsonStr).keys();
+       }
+       
+       /**
+        * Returns the name of the "root" property in the specified JSON doc. The
+        * "root" property is the single top-level property in the JSON doc. An
+        * exception is thrown if the doc is empty or if it contains more than one
+        * top-level property.
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @return the name of the "root" property
+        * @throws JSONException if the doc cannot be parsed, or if it is empty, or if
+        *         it contains more than one top-level property
+        */
+       public static String getJsonRootProperty(String jsonStr) throws JSONException {
+               Iterator<String> iter = getJsonIterator(jsonStr);
+
+               if (!iter.hasNext()) {
+                       throw new JSONException("Empty JSON object");
                }
+
+               String rootPropertyName = iter.next();
+
+               if (iter.hasNext()) {
+                       throw new JSONException("JSON object has more than one root property");
+               }
+
+               return rootPropertyName;
        }
 
        /**
@@ -161,11 +334,73 @@ public class JsonUtils {
                }
                return null;
        }
+       
+       
+       /**
+        * Invokes the getJsonRawValue() method with the wrap flag set to true
+        * and returns the String equivalent of the json node object returned.
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
+        * @return String field value associated with keys
+        */
+       public static String getJsonNodeValue(String jsonStr, String keys) {
+//             String isDebugLogEnabled = "true";
+               try {
+                               Object rawValue = getJsonRawValue(jsonStr, keys, true);
+                               if (rawValue == null) {
+                                       return null;
+                               } else {
+                                       if (rawValue instanceof String) {
+                                               msoLogger.debug("getJsonNodeValue(): the raw value is a String Object=" + ((String) rawValue).toString());
+                                               return (String) rawValue;
+                                       } else {
+                                               msoLogger.debug("getJsonNodeValue(): the raw value is NOT a String Object=" + rawValue.toString());
+                                               return rawValue.toString();
+                                       }
+                               }
+               } catch (Exception e) {
+                               msoLogger.debug("getJsonNodeValue(): unable to parse json to retrieve node for field=" + keys + ". Exception was: " + e.toString());
+               }
+               return null;
+       }
 
        /**
-        * Invokes the getJsonRawValue() method to obtain the JSONArray associated with
-        * the specified keys. The JSONArray is then walked to retrieve the content value of
-        * the specified field name.
+        * Invokes the getJsonRawValue() method and returns the String equivalent of
+        * the object returned.
+        * 
+        * TBD: May need separate methods for boolean, float, and integer fields if the
+        * String representation is not sufficient to meet client needs.
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
+        * @return String field value associated with keys
+        */
+       public static int getJsonIntValue(String jsonStr, String keys) {
+//             String isDebugLogEnabled = "true";
+               try {
+                               Object rawValue = getJsonRawValue(jsonStr, keys);
+                               if (rawValue == null) {
+                                       return 0;
+                               } else {
+                                       if (rawValue instanceof Integer) {
+                                               msoLogger.debug("getJsonValue(): the raw value is an Integer Object=" + ((String) rawValue).toString());
+                                               return (Integer) rawValue;
+                                       } else {
+                                               msoLogger.debug("getJsonValue(): the raw value is NOT an Integer Object=" + rawValue.toString());
+                                               return 0;
+                                       }
+                               }
+               } catch (Exception e) {
+                               msoLogger.debug("getJsonValue(): unable to parse json to retrieve value for field=" + keys + ". Exception was: " + e.toString());
+               }
+               return 0;
+       }
+
+       /**
+        * Invokes the getJsonParamValue() method to obtain the JSONArray associated with
+         * the specified keys. The JSONArray is then walked to retrieve the first array
+        * value associated with the specified field name (index=0).
         *
         * @param  jsonStr      String containing the JSON doc
         * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
@@ -173,6 +408,21 @@ public class JsonUtils {
         * @return String param value associated with field name
         */
        public static String getJsonParamValue(String jsonStr, String keys, String name) {
+               return getJsonParamValue(jsonStr, keys, name, 0);
+       }
+
+       /**
+        * Invokes the getJsonRawValue() method to obtain the JSONArray associated with
+        * the specified keys. The JSONArray is then walked to retrieve the nth array
+        * value associated with the specified field name and index
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
+        * @param  name         field name for the param to be retrieved
+        * @param  index    the nth param associated with name starting at 0
+        * @return String param value associated with field name
+        */
+       public static String getJsonParamValue(String jsonStr, String keys, String name, int index) {
 //             String isDebugLogEnabled = "true";
                try {
                        Object rawValue = getJsonRawValue(jsonStr, keys);
@@ -181,14 +431,28 @@ public class JsonUtils {
                        } else {
                                if (rawValue instanceof JSONArray) {
                                        msoLogger.debug("getJsonParamValue(): keys=" + keys + " points to JSONArray: " + ((JSONArray) rawValue).toString());
-                                       for (int i = 0; i < ((JSONArray) rawValue).length(); i++) {
+                                       int arrayLen = ((JSONArray) rawValue).length();
+                                       if (index < 0 || arrayLen < index+1) {
+                                               msoLogger.debug("getJsonParamValue(): index: " + index + " is out of bounds for array size of " + arrayLen);
+                                               return null;
+                                       }
+                                       int foundCnt = 0;
+                                       for (int i = 0; i < arrayLen; i++) {
                                                msoLogger.debug("getJsonParamValue(): index: " + i + ", value: " + ((JSONArray) rawValue).get(i).toString());
                                                if (((JSONArray) rawValue).get(i) instanceof JSONObject) {
                                                        msoLogger.debug("getJsonParamValue(): index: " + i + " is a JSONObject");
                                                        JSONObject jsonObj = (JSONObject)((JSONArray) rawValue).get(i);
-                                                       if (jsonObj.get("name").equals(name)) {
-                                                               msoLogger.debug("getJsonParamValue(): found value: " + (String) jsonObj.get("content") + " for name: " + name);
-                                                               return (String) jsonObj.get("content");
+                                                       String parmValue = jsonObj.get(name).toString();
+                                                       if (parmValue != null) {
+                                                               msoLogger.debug("getJsonParamValue(): found value: " + parmValue + " for name: " + name + " and index: " + i);
+                                                               if (foundCnt == index) {
+                                                                       return parmValue;
+                                                               } else {
+                                                                       foundCnt++;
+                                                                       continue;
+                                                               }
+                                                       } else {
+                                                               continue;
                                                        }
                                                } else {
                                                        msoLogger.debug("getJsonParamValue(): the JSONArray element is NOT a JSONObject=" + rawValue.toString());
@@ -275,6 +539,49 @@ public class JsonUtils {
                return keyValue;
        }
        
+       /**
+        * Walks the JSONObject (and sub-objects recursively), searching for the first value associated with the
+        * single key/field name specified. Returns the associated value if found or null if the key is not found
+        *
+        * @param  jsonObj      JSONObject representation of the the JSON doc
+        * @param  key          key to the target value
+        * @return String field value associated with key
+        */
+       public static Integer getJsonIntValueForKey(JSONObject jsonObj, String key) {
+//             String isDebugLogEnabled = "true";
+               Integer keyValue = 0;
+               try {
+                       if (jsonObj.has(key)) {
+                               msoLogger.debug("getJsonValueForKey(): found value for key=" + key);
+                               return ((Integer) jsonObj.get(key));
+                       } else {
+                               msoLogger.debug("getJsonValueForKey(): iterating over the keys");
+                               Iterator <String> itr = jsonObj.keys();
+                               while (itr.hasNext()) {
+                                       String nextKey = (String) itr.next();
+                                       Object obj = jsonObj.get(nextKey);
+                                       if (obj instanceof JSONObject) {
+                                               msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", points to JSONObject, recursive call");
+                                               keyValue = getJsonIntValueForKey((JSONObject) obj, key);
+                                               if (keyValue != null) {
+                                                       msoLogger.debug("getJsonValueForKey(): found value=" + keyValue + ", for key=" + key);
+                                                       break;
+                                               }
+                                       } else {
+                                               msoLogger.debug("getJsonValueForKey(): key=" + nextKey + ", does not point to a JSONObject, next key");
+                                       }
+                               }
+                       }
+               } catch (JSONException je) {
+                               // JSONObject::get() throws this exception if one of the specified keys is not found
+                               msoLogger.debug("getJsonValueForKey(): caught JSONException attempting to retrieve value for key=" + key);
+                               keyValue = null;
+               } catch (Exception e) {
+                               msoLogger.debug("getJsonValueForKey(): unable to parse json to retrieve value for field=" + key + ". Exception was: " + e.toString());
+               }
+               return keyValue;
+       }
+       
        /**
         * Boolean method to determine if a key path is valid for the JSON doc. Invokes
         * getJsonValue().
@@ -365,6 +672,22 @@ public class JsonUtils {
         * @return Object field value associated with keys
         */
        private static Object getJsonRawValue(String jsonStr, String keys) {
+               return getJsonRawValue(jsonStr, keys, false);
+       }       
+
+       /**
+        * Walks the JSON doc using the full key path to retrieve the associated
+        * value. All but the last key points to the 'parent' object name(s) in order
+        * in the JSON hierarchy with the last key pointing to the target value.
+        * The value returned is a Java object.
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
+        * * @param  wrap       Boolean which determines if returned JSONObjects sould be "wrapped"
+        *                  Note: wrap does not apply to returned scalar values 
+        * @return Object field value associated with keys
+        */
+       private static Object getJsonRawValue(String jsonStr, String keys, Boolean wrap) {
 //             String isDebugLogEnabled = "true";
                String keyStr = "";
                try {
@@ -383,11 +706,19 @@ public class JsonUtils {
                                        return keyValue;
                                }
                        }
-                       // we should not hit this point: either the key points to a valid value and
-                       // we return it above or the key is invalid and we handle the JSONException
-                       // below and return null
-                       return null;
-                       
+                       // return the json 'node' that the key points to
+                       // note: since this is a json object and not a scalar value,
+                       //       use the wrap flag to determine if the object should
+                       //       be wrapped with a root node value
+                       //       (the last key in the keys String)
+                       if (wrap) {
+                               JSONObject wrappedJsonObj = new JSONObject();
+                               wrappedJsonObj.put(keyStr, jsonObj);
+                               return wrappedJsonObj.toString();
+                       } else {
+                               return jsonObj.toString();
+                       }
+
                } catch (JSONException je) {
                                // JSONObject::get() throws this exception if one of the specified keys is not found
                                msoLogger.debug("getJsonRawValue(): caught JSONException attempting to retrieve raw value for key=" + keyStr);
@@ -439,5 +770,61 @@ public class JsonUtils {
                }
                return null;
        }
+
+       /**
+        * This json util method converts a json "Key" and "Value"
+        * entry Array to a Java map.
+        *
+        * @param execution
+        * @param entryArray - the json value of the entry Array
+        *
+        * @return map - a Map containing the entries
+        *
+        */
+       public Map<String, String> entryArrayToMap(Execution execution, String entryArray) {
+               msoLogger.debug("Started Entry Array To Map Util Method");
+
+               Map<String, String> map = new HashMap<String, String>();
+
+               //Populate Map
+               String entryListJson = "{ \"entry\":" + entryArray + "}";
+               JSONObject obj = new JSONObject(entryListJson);
+               JSONArray arr = obj.getJSONArray("entry");
+               for (int i = 0; i < arr.length(); i++){
+                       JSONObject jo = arr.getJSONObject(i);
+                       String key = jo.getString("key");
+                       String value =jo.getString("value");
+                       map.put(key, value);
+               }
+               msoLogger.debug("Outgoing Map is: " + map);
+               msoLogger.debug("Completed Entry Array To Map Util Method");
+               return map;
+       }
+
+
+       /**
+        * Invokes the getJsonRawValue() method to determine if the
+        * json element/variable exist. Returns true if the
+        * json element exist
+        *
+        * @param  jsonStr      String containing the JSON doc
+        * @param  keys         full key path to the target value in the format of "key1.key2.key3..."
+        * @return boolean field value associated with keys
+        */
+       public static boolean jsonElementExist(String jsonStr, String keys) {
+
+               try {
+                       Object rawValue = getJsonRawValue(jsonStr, keys);
+                       if (rawValue == null) {
+                               return false;
+                       } else {
+                               return true;
+                       }
+               } catch (Exception e) {
+                               msoLogger.debug("jsonElementExist(): unable to determine if json element exist. Exception is: " + e.toString());
+               }
+               return true;
+       }
+
 }