JSONUtils.java [src/csip/utils] Revision: beaf35d680e39fda49d78cf7e170b55dc5710c27  Date: Tue Apr 25 16:47:08 MDT 2017
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API and application suite.
 *
 * 2012-2017, Olaf David and others, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package csip.utils;

import csip.Config;
import csip.ModelDataService;
import static csip.ModelDataService.KEY_PARAMETER;
import static csip.ModelDataService.KEY_RESULT;
import csip.ServiceException;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.io.FileUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.codehaus.jettison.json.JSONTokener;

/**
 *
 * @author od
 */
public class JSONUtils {

    public static int[] toIntArray(JSONArray arr) throws JSONException {
        int[] a = new int[arr.length()];
        for (int i = 0; i < a.length; i++) {
            a[i] = arr.getInt(i);
        }
        return a;
    }


    public static boolean[] toBooleanArray(JSONArray arr) throws JSONException {
        boolean[] a = new boolean[arr.length()];
        for (int i = 0; i < a.length; i++) {
            a[i] = arr.getBoolean(i);
        }
        return a;
    }


    public static long[] toLongArray(JSONArray arr) throws JSONException {
        long[] a = new long[arr.length()];
        for (int i = 0; i < a.length; i++) {
            a[i] = arr.getLong(i);
        }
        return a;
    }


    public static double[] toDoubleArray(JSONArray arr) throws JSONException {
        double[] a = new double[arr.length()];
        for (int i = 0; i < a.length; i++) {
            a[i] = arr.getDouble(i);
        }
        return a;
    }


    public static String[] toStringArray(JSONArray arr) throws JSONException {
        String[] a = new String[arr.length()];
        for (int i = 0; i < a.length; i++) {
            a[i] = arr.getString(i);
        }
        return a;
    }


    public static JSONArray toArray(double[] val) {
        JSONArray arr = new JSONArray(val.length);
        try {
            for (double d : val) {
                arr.put(d);
            }
        } catch (JSONException ex) {
            return arr;
        }
        return arr;
    }


    public static JSONArray toArray(boolean[] val) {
        JSONArray arr = new JSONArray(val.length);
        for (boolean d : val) {
            arr.put(d);
        }
        return arr;
    }


    public static JSONArray toArray(long[] val) {
        JSONArray arr = new JSONArray(val.length);
        for (long d : val) {
            arr.put(d);
        }
        return arr;
    }


    public static JSONArray toArray(int[] val) {
        JSONArray arr = new JSONArray(val.length);
        for (int d : val) {
            arr.put(d);
        }
        return arr;
    }


    public static JSONArray toArray(String[] val) {
        JSONArray arr = new JSONArray(val.length);
        for (String d : val) {
            arr.put(d);
        }
        return arr;
    }


    public static JSONObject clone(JSONObject o) throws JSONException {
        return new JSONObject(o.toString());
    }


    public static String[] getNames(JSONObject o) {
        Iterator<?> i = o.keys();
        ArrayList<String> l = new ArrayList<>();
        while (i.hasNext()) {
            l.add(i.next().toString());
        }
        return l.toArray(new String[l.size()]);
    }


    public static boolean getBooleanParam(Map<String, JSONObject> param, String key, boolean def) {
        try {
            return (param.get(key) != null) ? param.get(key).getBoolean(ModelDataService.VALUE) : def;
        } catch (JSONException ex) {
            return def;
        }
    }


    public static int getIntParam(Map<String, JSONObject> param, String key, int def) {
        try {
            return (param.get(key) != null) ? param.get(key).getInt(ModelDataService.VALUE) : def;
        } catch (JSONException ex) {
            return def;
        }
    }


    public static double getDoubleParam(Map<String, JSONObject> param, String key, double def) {
        try {
            return (param.get(key) != null) ? param.get(key).getDouble(ModelDataService.VALUE) : def;
        } catch (JSONException ex) {
            return def;
        }
    }


    public static long getJSONLong(JSONObject o, String key, long def) {
        try {
            return o.getLong(key);
        } catch (JSONException ex) {
            return def;
        }
    }


    public static int getJSONInt(JSONObject o, String key, int def) {
        try {
            return o.getInt(key);
        } catch (JSONException ex) {
            return def;
        }
    }


    public static String getJSONString(JSONObject o, String key, String def) {
        try {
            return o.getString(key);
        } catch (JSONException ex) {
            return def;
        }
    }


    public static boolean getJSONBoolean(JSONObject o, String key, boolean def) {
        try {
            return o.getBoolean(key);
        } catch (JSONException ex) {
            return def;
        }
    }


    public static String getStringParam(Map<String, JSONObject> param, String key, String def) {
        try {
            return (param.get(key) != null) ? param.get(key).getString(ModelDataService.VALUE) : def;
        } catch (JSONException ex) {
            return def;
        }
    }


    public static JSONArray getJSONArrayParam(Map<String, JSONObject> param, String key) {
        try {
            return (param.get(key) != null) ? param.get(key).getJSONArray(ModelDataService.VALUE) : null;
        } catch (JSONException ex) {
            return null;
        }
    }


    public static JSONObject getJSONObjectParam(Map<String, JSONObject> param, String key) {
        try {
            return (param.get(key) != null) ? param.get(key).getJSONObject(ModelDataService.VALUE) : null;
        } catch (JSONException ex) {
            return null;
        }
    }


    public static JSONObject getJSONObjectGeometry(Map<String, JSONObject> param, String key) {
        try {
            return (param.get(key) != null) ? param.get(key).getJSONObject(ModelDataService.GEOMETRY) : null;
        } catch (JSONException ex) {
            return null;
        }
    }


    public static void checkDouble(String msg, double val, double min, double max) {
        if (Double.isNaN(val)) {
            throw new IllegalArgumentException(msg + " no valid input " + val);
        }
        if (val < min || val > max) {
            throw new IllegalArgumentException(msg + " illegal value: " + val);
        }
    }


    public static List<String> getRequestedResults(JSONObject metainfo) throws ServiceException {
        List<String> l = new ArrayList<>();
        try {
            JSONArray j = metainfo.getJSONArray(ModelDataService.KEY_REQUEST_RESULTS);
            for (int i = 0; i < j.length(); i++) {
                l.add(j.getString(i));
            }
        } catch (JSONException ex) {
            throw new ServiceException("No results requested.");
        }
        return l;
    }


    public static void checkValidResultRequest(JSONObject metainfo, Collection<String> results) throws ServiceException {
        try {
            JSONArray j = metainfo.getJSONArray(ModelDataService.KEY_REQUEST_RESULTS);
            for (int i = 0; i < j.length(); i++) {
                String name = j.getString(i);
                if (!results.contains(name)) {
                    throw new ServiceException("unknown result request :" + name);
                }
            }
        } catch (JSONException ex) {
            throw new ServiceException("No results requested. Add one or more of : " + results.toString());
        }
    }


    public static void checkKeyExists(Map<String, JSONObject> params, String key) throws ServiceException {
        JSONObject j = params.get(key);
        if (j == null) {
            throw new ServiceException("Key not found :" + key);
        }
    }


    public static boolean checkKeyExistsB(Map<String, JSONObject> params, String key) {
        JSONObject j = params.get(key);
        return j != null;
    }


    public static boolean checkArrayExists(JSONObject obj, String arrayKey) {
        try {
            obj.getJSONArray(arrayKey);
            return true;
        } catch (JSONException e) {
            return false;
        }
    }


    public static void checkFileExists(JSONObject param, File dir) throws JSONException, ServiceException {
        String file = param.getString(ModelDataService.VALUE);
        if (!new File(dir, file).exists()) {
            throw new ServiceException("File not found :" + param.getString(ModelDataService.VALUE));
        }
    }


    public static Map<String, JSONObject> getParameter(JSONObject request) throws JSONException {
        JSONArray param = request.getJSONArray(KEY_PARAMETER);
        Map<String, JSONObject> pm = JSONUtils.preprocess(param);
        return pm;
    }


    public static Map<String, JSONObject> getResults(JSONObject request) throws JSONException {
        JSONArray param = request.getJSONArray(KEY_RESULT);
        Map<String, JSONObject> pm = JSONUtils.preprocess(param);
        return pm;
    }


    public static String getErrorStatus(JSONObject request) throws Exception {
        JSONObject metainfo = request.getJSONObject(ModelDataService.KEY_METAINFO);
        if (getStatus(request).equals(ModelDataService.FINISHED) && hasResult(request)) {
            return null;
        } else if (getStatus(request).equals(ModelDataService.SUBMITTED)) {
            return null;
        } else if (getStatus(request).equals(ModelDataService.RUNNING)) {
            return null;
        } else if (getStatus(request).equals(ModelDataService.FAILED) && metainfo.has("Error")) {
            return metainfo.getString("Error");
        }
        return "Error";
    }


    public static Map<String, JSONObject> preprocess(JSONArray params) throws JSONException {
        Map<String, JSONObject> p = new HashMap<>();
        for (int i = 0; i < params.length(); i++) {
            JSONObject o = params.getJSONObject(i);
            p.put(o.getString(ModelDataService.KEY_NAME), o);
        }
        return p;
    }


    public static JSONArray preprocess(Map<String, JSONObject> params) throws JSONException {
        JSONArray arr = new JSONArray();
// sort alphabetically        
        SortedSet<String> keys = new TreeSet<>(params.keySet());
        for (String key : keys) {
//      for (JSONObject value : params.values()) {
            JSONObject value = params.get(key);
//            arr.put(value);
//        }
            arr.put(value);
        }
        return arr;
    }


    public static JSONObject newRequest(JSONArray parameter, JSONObject metainfo) {
        JSONObject req = new JSONObject();
        try {
            metainfo.put(ModelDataService.KEY_TSTAMP, Dates.nowISO());
            req.put(ModelDataService.KEY_METAINFO, metainfo);
            req.put(ModelDataService.KEY_PARAMETER, parameter);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return req;
    }


    public static void putRequestedMetaInfo(JSONObject req, JSONObject res, String key, Object val) throws JSONException {
        if (req.getJSONObject(ModelDataService.KEY_METAINFO).has(key)) {
            res.getJSONObject(ModelDataService.KEY_METAINFO).put(key, val);
        }
    }


    public static void putRequestedMetaInfo(JSONObject metainfo, String key, Object val) throws JSONException {
        if (metainfo.has(key)) {
            metainfo.put(key, val);
        }
    }


    public static JSONObject newResponse() {
        JSONArray param = new JSONArray();
        JSONArray result = new JSONArray();
        JSONObject metainfo = new JSONObject();
        return newResponse(param, result, metainfo);
    }


    public static JSONObject newRequest() {
        JSONArray param = new JSONArray();
        JSONObject metainfo = new JSONObject();
        return newResponse(param, null, metainfo);
    }


    public static JSONObject newRequest(Map<String, JSONObject> params) throws JSONException {
        JSONObject metainfo = new JSONObject();
        return newResponse(preprocess(params), null, metainfo);
    }


    public static JSONObject newRequest(Map<String, JSONObject> params, JSONObject metainfo) throws JSONException {
        return newResponse(preprocess(params), null, metainfo);
    }


    public static JSONObject newRequest(JSONObject metainfo) {
        JSONArray param = new JSONArray();
        return newResponse(param, null, metainfo);
    }


    public static JSONObject getMetaInfo(JSONObject object) throws ServiceException {
        try {
            return object.getJSONObject(ModelDataService.KEY_METAINFO);
        } catch (JSONException ex) {
            throw new ServiceException(ex);
        }
    }


    public static JSONObject newResponse(JSONObject request, JSONArray result, JSONObject metainfo) throws ServiceException {
        try {
            request.put(ModelDataService.KEY_METAINFO, metainfo);
            if (result != null) {
                request.put(ModelDataService.KEY_RESULT, result);
            }
        } catch (JSONException ex) {
            throw new ServiceException(ex);
        }
        return request;
    }


    public static JSONObject newResponse(JSONArray parameter, JSONArray result, JSONObject metainfo) {
        JSONObject req = new JSONObject();
        try {
            req.put(ModelDataService.KEY_METAINFO, metainfo);
            if (parameter != null) {
                req.put(ModelDataService.KEY_PARAMETER, parameter);
            }
            if (result != null) {
                req.put(ModelDataService.KEY_RESULT, result);
            }
        } catch (JSONException ex) {
            throw new RuntimeException(ex);
        }
        return req;
    }


    public static String getErrorMessage(Throwable e) {
        String message = e.getMessage();
        if (message == null) {
            message = e.getClass().toString();
        }
        return message;
    }


    public static String getStringStackTrace(Throwable e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.close();
        return sw.toString();
    }


    public static JSONArray getJSONStackTrace(Throwable e) {
        String s = getStringStackTrace(e);
        JSONArray arr = new JSONArray();
        for (String st : s.split("\n")) {
            arr.put(st.replace('\t', ' '));
        }
        return arr;
    }


    @Deprecated
    public static JSONObject newError(JSONArray parameter, Exception E) {
        JSONObject resp = new JSONObject();
        JSONObject meta = new JSONObject();
        JSONArray result = new JSONArray();
        try {
            meta.put(ModelDataService.KEY_STATUS, ModelDataService.FAILED);
            meta.put(ModelDataService.KEY_TSTAMP, Dates.nowISO());
            resp.put(ModelDataService.KEY_METAINFO, meta);
            result.put(JSONUtils.error(getStringStackTrace(E)));
            if (parameter != null) {
                resp.put(ModelDataService.KEY_PARAMETER, parameter);
            }
            resp.put(ModelDataService.KEY_RESULT, result);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return resp;
    }


    public static JSONObject newError(JSONObject meta, JSONArray parameter, Throwable err) {
        JSONObject resp = new JSONObject();
        try {
            meta.put(ModelDataService.ERROR, getErrorMessage(err));
            if (Config.getBoolean("csip.response.stacktrace")) {
                JSONArray trace = getJSONStackTrace(err);
                if (trace != null) {
                    meta.put("stacktrace", trace);
                }
            }
            resp.put(ModelDataService.KEY_METAINFO, meta);
            if (parameter != null) {
                resp.put(ModelDataService.KEY_PARAMETER, parameter);
            }
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return resp;
    }


    public static JSONObject data(String name, Object value) throws JSONException {
        return data(name, value, null);
    }


    public static JSONObject data(String name, Object value, String unit) throws JSONException {
        JSONObject param = new JSONObject();
        param.put(ModelDataService.KEY_NAME, name);
        param.put(ModelDataService.VALUE, value);
        if (unit != null) {
            param.put(ModelDataService.KEY_UNIT, unit);
        }
        return param;
    }


    public static JSONObject dataDesc(String name, Object value, String desc) throws JSONException {
        JSONObject param = new JSONObject();
        param.put(ModelDataService.KEY_NAME, name);
        param.put(ModelDataService.VALUE, value);
        if (desc != null) {
            param.put(ModelDataService.KEY_DESC, desc);
        }
        return param;
    }


    public static JSONObject data(String name, Object value, String descr, String unit) {
        return dataUnitDesc(name, value, unit, descr);
    }


    public static JSONObject dataUnitDesc(String name, Object value, String unit, String desc) {
        JSONObject param = new JSONObject();
        try {
            param.put(ModelDataService.KEY_NAME, name);
            param.put(ModelDataService.VALUE, value);
            if (unit != null) {
                param.put(ModelDataService.KEY_UNIT, unit);
            }
            if (desc != null) {
                param.put(ModelDataService.KEY_DESC, desc);
            }
            return param;
        } catch (JSONException ex) {
            throw new IllegalArgumentException(ex);
        }
    }


    public static JSONObject error(String text) {
        JSONObject o = new JSONObject();
        try {
            o.put(ModelDataService.ERROR, text);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return o;
    }


    public static JSONObject ok(String text) {
        JSONObject o = new JSONObject();
        try {
            o.put(ModelDataService.OK, text);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return o;
    }


    public static String getValue(JSONObject o) {
        try {
            return o.getString(ModelDataService.VALUE);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return null;
    }


    public static String getValueByKey(JSONArray a, String key) {
        try {
            for (int i = 0; i < a.length(); i++) {
                JSONObject attr = a.getJSONObject(i);
                if (attr.getString(ModelDataService.KEY_NAME).equals(key)) {
                    return attr.getString(ModelDataService.VALUE);
                }
            }
            throw new JSONException("Key not found in array=" + key);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return null;
    }


    public static String getUnit(JSONObject o) {
        try {
            return o.getString(ModelDataService.UNIT);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return null;
    }


    public static boolean hasResult(JSONObject r) throws Exception {
        if (r.has("result")) {
            JSONArray response_result = r.getJSONArray("result");
            return response_result.length() > 0;
        }
        return false;
    }


    public static String getSID(JSONObject r) throws JSONException {
        JSONObject meta = r.getJSONObject("metainfo");
        if (meta.has("suid")) {
            return meta.getString("suid");
        }
        return "";
    }


    public static boolean isAsync(JSONObject r) throws JSONException {
        JSONObject meta = r.getJSONObject("metainfo");
        if (meta.has("mode")) {
            String mode = meta.getString("mode");
            return mode.toLowerCase().equals("async");
        }
        return false;
    }


    public static String getStatus(JSONObject r) throws JSONException {
        JSONObject meta = r.getJSONObject("metainfo");
        if (meta.has("status")) {
            return meta.getString("status");
        }
        return "unknown";
    }


    public boolean hasRange(JSONObject o) {
        return o.has(ModelDataService.RANGE);
    }


    public static double getRangeMin(JSONObject o) {
        try {
            return o.getJSONObject(ModelDataService.RANGE).getDouble(ModelDataService.MIN);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return Double.MIN_VALUE;
    }


    public static double getRangeMax(JSONObject o) throws JSONException {
        try {
            return o.getJSONObject(ModelDataService.RANGE).getDouble(ModelDataService.MAX);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return Double.MAX_VALUE;
    }


    public static String getDescription(JSONObject o) {
        try {
            return o.getString(ModelDataService.KEY_DESC);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return null;
    }


    public boolean hasIntent(JSONObject o) {
        return o.has(ModelDataService.INTENT);
    }


    public static boolean isIn(JSONObject o) {
        try {
            return o.getString(ModelDataService.INTENT).toLowerCase().contains(ModelDataService.IN);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return false;
    }


    public static boolean isOut(JSONObject o) {
        try {
            return o.getString(ModelDataService.INTENT).toLowerCase().contains(ModelDataService.OUT);
        } catch (JSONException ex) {
            ex.printStackTrace(System.err);
        }
        return false;
    }


    public static boolean isInOut(JSONObject o) {
        return isIn(o) && isOut(o);
    }


    public static void main(String[] args) throws JSONException, IOException {
        String a = FileUtils.readFileToString(new File("/od/projects/csip-all/csip-lmod/test/service_tests/d_contour_1_0__contour_1.json"));
        try {
            JSONObject o = new JSONObject(a);
        } catch (JSONException E) {
            System.out.println("Malformed JSON request.");
        }
//        System.out.println(o.toString(4));

//        String myString = new JSONObject().put("/JS/ON", "'Hel//lo, Worl//d!'/").toString();
//        System.out.println(myString.replace("\\/", "/"));
    }

}