All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.almworks.jira.structure.api.util.JsonMapUtil Maven / Gradle / Ivy

The newest version!
package com.almworks.jira.structure.api.util;

import com.atlassian.annotations.Internal;
import org.jetbrains.annotations.*;
import org.json.*;

import java.util.*;

/**
 * Utility methods for working with JSON maps.
 */
public class JsonMapUtil {
  @Contract("_, false, _, _ -> !null")
  public static Map copyParameters(Map parameters, boolean allowNull,
    boolean makeImmutable, boolean verify)
  {
    boolean empty = parameters == null || parameters.isEmpty();
    if (empty) {
      if (allowNull) return null;
      if (makeImmutable) return Collections.emptyMap();
    }
    return mergeParameters(makeImmutable, verify, parameters);
  }

  @NotNull
  public static Map mergeParameters(boolean makeImmutable, boolean verify, Map... parameters) {
    LinkedHashMap r = new LinkedHashMap<>();
    if (parameters != null) {
      for (Map map : parameters) {
        if (map != null) {
          for (Map.Entry e : map.entrySet()) {
            Object key = e.getKey();
            Object value = e.getValue();
            if (verify) {
              if (key == null) {
                throw new IllegalArgumentException("null key");
              }
              if (!(key instanceof String)) {
                throw new IllegalArgumentException("non-string key: " + key);
              }
              checkValidParameter(value);
            }
            r.put((String) key, copyParameter(value, makeImmutable));
          }
        }
      }
    }
    return makeImmutable ? Collections.unmodifiableMap(r) : r;
  }

  public static Object copyParameter(Object value, boolean makeImmutable) {
    value = unwrapJsonCollection(value);
    if (value instanceof List) {
      List list = (List) value;
      List r = new ArrayList(list.size());
      for (Object elem : list) {
        r.add(copyParameter(elem, makeImmutable));
      }
      return makeImmutable ? Collections.unmodifiableList(r) : r;
    }
    if (value instanceof Map) {
      Map map = (Map) value;
      Map r = new LinkedHashMap();
      for (Map.Entry e : map.entrySet()) {
        r.put(String.valueOf(e.getKey()), copyParameter(e.getValue(), makeImmutable));
      }
      return makeImmutable ? Collections.unmodifiableMap(r) : r;
    }
    return value;
  }

  public static void checkValidParameter(Object value) throws IllegalArgumentException {
    try {
      checkValidParameter0(value);
    } catch (StackOverflowError e) {
      // protection against very unlikely cycled collection
      throw new IllegalArgumentException("stack overflow", e);
    }
  }

  private static void checkValidParameter0(Object value) throws IllegalArgumentException {
    if (value == null) {
      throw new IllegalArgumentException("null value");
    }
    if (value instanceof String || value instanceof Integer || value instanceof Long
      || value instanceof Double || value instanceof Boolean)
    {
      return;
    }
    value = unwrapJsonCollection(value);

    if (value instanceof List) {
      List list = (List) value;
      int index = 0;
      for (Object elem : list) {
        try {
          checkValidParameter0(elem);
        } catch (IllegalArgumentException ex){
          throw new IllegalArgumentException(
            "invalid list: invalid value at index " + index + ": " + ex.getMessage(), ex);
        }
        index++;
      }
      return;
    }
    if (value instanceof Map) {
      Map map = (Map) value;
      for (Map.Entry e : map.entrySet()) {
        if (!(e.getKey() instanceof String)) {
          throw new IllegalArgumentException("invalid map: non-string key " + e.getKey());
        }
        try {
          checkValidParameter0(e.getValue());
        } catch (IllegalArgumentException ex) {
          throw new IllegalArgumentException(
            "invalid map: invalid value for key " + e.getKey() + ": " + ex.getMessage(), ex);
        }
      }
      return;
    }
    throw new IllegalArgumentException("invalid value type: " + value.getClass().getName());
  }

  public static Object unwrapJsonCollection(Object value) {
    try {
      if (value instanceof JSONArray) {
        return jsonToList((JSONArray) value);
      } else if (value instanceof JSONObject) {
        return jsonToMap((JSONObject) value);
      }
      return value;
    } catch (JSONException e) {
      throw new IllegalArgumentException("failed to convert json object: " + e.getMessage());
    }
  }

  @Internal
  public static List jsonToList(JSONArray jsonArray) throws JSONException {
    List results = new ArrayList<>(jsonArray.length());
    for (int i = 0; i < jsonArray.length(); i++) {
      Object element = jsonArray.get(i);
      if (element == null || JSONObject.NULL.equals(element)) {
        results.add(null);
      } else if (element instanceof JSONArray) {
        results.add(jsonToList((JSONArray) element));
      } else if (element instanceof JSONObject) {
        results.add(jsonToMap((JSONObject) element));
      } else {
        results.add(element);
      }
    }
    return results;
  }

  @Internal
  public static Map jsonToMap(JSONObject jsonObject) throws JSONException {
    Map results = new HashMap<>();
    for (Iterator it = jsonObject.keys(); it.hasNext(); ) {
      String key = (String) it.next();
      Object value = jsonObject.get(key);
      if (value == null || JSONObject.NULL.equals(value)) {
        results.put(key, null);
      } else if (value instanceof JSONObject) {
        results.put(key, jsonToMap((JSONObject) value));
      } else if (value instanceof JSONArray) {
        results.put(key, jsonToList((JSONArray) value));
      } else {
        results.put(key, value);
      }
    }
    return results;
  }
}