public static void registerObjectsExportedDefinitions(
      @NotNull VirtualFile key,
      @NotNull final JsonSchemaExportedDefinitions definitionsObject,
      @NotNull final JsonSchemaObject object) {
    String id = object.getId();
    if (!StringUtil.isEmptyOrSpaces(id)) {
      id = id.endsWith("#") ? id.substring(0, id.length() - 1) : id;
      final BiFunction<String, Map<String, JsonSchemaObject>, Map<String, JsonSchemaObject>>
          convertor =
              (s, map) -> {
                final Map<String, JsonSchemaObject> converted = new HashMap<>();
                for (Map.Entry<String, JsonSchemaObject> entry : map.entrySet()) {
                  String key1 = entry.getKey();
                  key1 = key1.startsWith("/") ? key1.substring(1) : key1;
                  converted.put(s + key1, entry.getValue());
                }
                return converted;
              };

      final HashMap<String, JsonSchemaObject> map = new HashMap<>();
      map.put("", object);
      final Map<String, JsonSchemaObject> definitions = object.getDefinitions();
      if (definitions != null && !definitions.isEmpty()) {
        map.putAll(convertor.apply("#/definitions/", definitions));
      }
      final Map<String, JsonSchemaObject> properties = object.getProperties();
      if (properties != null && !properties.isEmpty()) {
        map.putAll(convertor.apply("#/properties/", properties));
      }
      definitionsObject.register(key, id, map);
    }
  }
  @NotNull
  public static JsonSchemaObject findRelativeDefinition(
      @NotNull String ref, @NotNull JsonSchemaObject root) {
    if ("#".equals(ref)) {
      return root;
    }
    if (!ref.startsWith("#/"))
      throw new RuntimeException("Non-relative or erroneous reference: " + ref);
    ref = ref.substring(2);
    final String[] parts = ref.split("/");
    JsonSchemaObject current = root;
    for (int i = 0; i < parts.length; i++) {
      if (current == null) throw new RuntimeException("Incorrect reference: " + ref);
      final String part = parts[i];
      if ("definitions".equals(part)) {
        if (i == (parts.length - 1))
          throw new RuntimeException("Incorrect definition reference: " + ref);
        //noinspection AssignmentToForLoopParameter
        current = current.getDefinitions().get(parts[++i]);
        continue;
      }
      if ("properties".equals(part)) {
        if (i == (parts.length - 1))
          throw new RuntimeException("Incorrect properties reference: " + ref);
        //noinspection AssignmentToForLoopParameter
        current = current.getProperties().get(parts[++i]);
        continue;
      }

      current = current.getDefinitions().get(part);
    }
    if (current == null) throw new RuntimeException("Incorrect reference: " + ref);
    return current;
  }
  private static void removeDefinitions(
      JsonSchemaObject root, ArrayList<JsonSchemaObject> objects) {
    final List<JsonSchemaObject> queue = new ArrayList<>(objects.size() + 1);
    queue.addAll(objects);
    queue.add(root);

    for (JsonSchemaObject object : queue) {
      final Map<String, JsonSchemaObject> definitions = object.getDefinitions();
      if (definitions != null) {
        objects.removeAll(definitions.values());
      }
    }
  }
 void readSingleDefinition(JsonReader in, String name, JsonSchemaObject object)
     throws IOException {
   if (in.peek() != JsonToken.BEGIN_OBJECT) {
     in
         .skipValue(); // if unknown property has non-object value, than it is not a definition,
                       // lets ignore it
     return;
   }
   final JsonSchemaObject defined = read(in);
   if (defined == null) return;
   Map<String, JsonSchemaObject> definitions = object.getDefinitions();
   if (definitions == null) {
     object.setDefinitions(definitions = new HashMap<>());
   }
   definitions.put(name, defined);
 }