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

org.sdase.commons.shared.asyncapi.AsyncBuilder Maven / Gradle / Ivy

Go to download

A libraries to bootstrap services easily that follow the patterns and specifications promoted by the SDA SE

There is a newer version: 7.0.88
Show newest version
package org.sdase.commons.shared.asyncapi;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.sdase.commons.shared.asyncapi.jsonschema.JsonSchemaBuilder;
import org.sdase.commons.shared.asyncapi.jsonschema.victools.VictoolsJsonSchemaBuilder;
import org.sdase.commons.shared.asyncapi.util.JsonNodeUtil;
import org.sdase.commons.shared.asyncapi.util.RefUtil;

public class AsyncBuilder
    implements AsyncApiGenerator.AsyncApiBaseBuilder,
        AsyncApiGenerator.SchemaBuilder,
        FinalBuilder {

  private JsonNode asyncApiBaseTemplate;
  private JsonSchemaBuilder jsonSchemaBuilder;

  public AsyncBuilder() {
    this.jsonSchemaBuilder = VictoolsJsonSchemaBuilder.fromDefaultConfig();
  }

  @Override
  public AsyncApiGenerator.SchemaBuilder withAsyncApiBase(String yamlAsyncApiContent) {
    try {
      asyncApiBaseTemplate = YAMLMapper.builder().build().readTree(yamlAsyncApiContent);
    } catch (IOException e) {
      throw new UncheckedIOException("Error while converting YAML to JSONNode", e);
    }
    return this;
  }

  @Override
  public FinalBuilder withJsonSchemaBuilder(JsonSchemaBuilder jsonSchemaBuilder) {
    this.jsonSchemaBuilder = jsonSchemaBuilder;
    return this;
  }

  @Override
  public JsonNode generate() {
    ObjectNode asyncApiObject = asyncApiBaseTemplate.deepCopy();
    var jsonSchemas = createSchemasFromReferencedClasses(asyncApiObject);
    insertSchemas(jsonSchemas, asyncApiObject);
    JsonNodeUtil.sortJsonNodeInPlace(asyncApiObject.at("/components/schemas"));
    return asyncApiObject;
  }

  private Map createSchemasFromReferencedClasses(ObjectNode asyncApi) {
    var types =
        findRequiredSchemas(asyncApi).stream().map(this::toType).collect(Collectors.toSet());
    return jsonSchemaBuilder.toJsonSchema(types);
  }

  private Set findRequiredSchemas(JsonNode asyncApiJsonNode) {
    String prefix = "class://";
    Set result = new LinkedHashSet<>();
    RefUtil.updateAllRefsRecursively(
        asyncApiJsonNode,
        ref -> {
          String refText = ref.asText();
          if (refText.startsWith(prefix)) {
            result.add(refText.substring(prefix.length()));
            String simpleClassName = refText.substring(refText.lastIndexOf(".") + 1);
            return "#/components/schemas/%s".formatted(simpleClassName);
          }
          return refText;
        });
    return result;
  }

  private void insertSchemas(Map newSchemas, ObjectNode targetAsyncApiObject) {
    ObjectNode components = getOrCreateObject(targetAsyncApiObject, "components");
    ObjectNode targetSchemas = getOrCreateObject(components, "schemas");
    newSchemas.forEach(targetSchemas::set);
  }

  private ObjectNode getOrCreateObject(ObjectNode source, String fieldName) {
    if (source.has(fieldName)) {
      JsonNode jsonNode = source.get(fieldName);
      if (jsonNode instanceof ObjectNode objectNode) {
        return objectNode;
      }
      throw new IllegalStateException(
          "'%s' is not an Object node but a %s in %s"
              .formatted(fieldName, jsonNode.getClass().getSimpleName(), source));
    }
    ObjectNode newObjectNode = source.objectNode();
    source.set(fieldName, newObjectNode);
    return newObjectNode;
  }

  private Type toType(String fullyQualifiedClassName) {
    try {
      return getClass().getClassLoader().loadClass(fullyQualifiedClassName);
    } catch (ClassNotFoundException e) {
      throw new ReferencedClassNotFoundException(e);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy