datahub/buildSrc/src/main/java/io/datahubproject/OpenApiEntities.java
2024-03-23 06:15:36 -05:00

673 lines
34 KiB
Java

package io.datahubproject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.linkedin.metadata.models.registry.config.Entities;
import com.linkedin.metadata.models.registry.config.Entity;
import org.gradle.internal.Pair;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class OpenApiEntities {
private final static String MODEL_VERSION = "_v2";
private final static String REQUEST_SUFFIX = "Request" + MODEL_VERSION;
private final static String RESPONSE_SUFFIX = "Response" + MODEL_VERSION;
private final static String ASPECT_REQUEST_SUFFIX = "Aspect" + REQUEST_SUFFIX;
private final static String ASPECT_RESPONSE_SUFFIX = "Aspect" + RESPONSE_SUFFIX;
private final static String ENTITY_REQUEST_SUFFIX = "Entity" + REQUEST_SUFFIX;
private final static String ENTITY_RESPONSE_SUFFIX = "Entity" + RESPONSE_SUFFIX;
private final JsonNodeFactory NODE_FACTORY;
private Map<String, Entity> entityMap;
private String entityRegistryYaml;
private Path combinedDirectory;
private final static ImmutableSet<Object> SUPPORTED_ASPECT_PATHS = ImmutableSet.builder()
.add("domains")
.add("ownership")
.add("deprecation")
.add("status")
.add("globalTags")
.add("glossaryTerms")
.add("dataContractInfo")
.add("browsePathsV2")
.add("datasetProperties").add("editableDatasetProperties")
.add("chartInfo").add("editableChartProperties")
.add("dashboardInfo").add("editableDashboardProperties")
.add("notebookInfo").add("editableNotebookProperties")
.add("dataProductProperties")
.add("institutionalMemory")
.add("forms").add("formInfo").add("dynamicFormAssignment")
.build();
private final static ImmutableSet<String> ENTITY_EXCLUSIONS = ImmutableSet.<String>builder()
.add("structuredProperty")
.build();
public OpenApiEntities(JsonNodeFactory NODE_FACTORY) {
this.NODE_FACTORY = NODE_FACTORY;
}
public String getEntityRegistryYaml() {
return entityRegistryYaml;
}
public void setEntityRegistryYaml(String entityRegistryYaml) {
this.entityRegistryYaml = entityRegistryYaml;
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.findAndRegisterModules();
try {
Entities entities = mapper.readValue(Paths.get(entityRegistryYaml).toFile(), Entities.class);
entityMap = entities.getEntities().stream()
.filter(e -> "core".equals(e.getCategory()))
.collect(Collectors.toMap(Entity::getName, Function.identity()));
} catch (IOException e) {
throw new IllegalArgumentException(
String.format("Error while reading entity yaml file in path %s: %s", entityRegistryYaml, e.getMessage()));
}
}
public Path getCombinedDirectory() {
return combinedDirectory;
}
public void setCombinedDirectory(Path combinedDirectory) {
this.combinedDirectory = combinedDirectory;
}
public ObjectNode entityExtension(List<ObjectNode> nodesList, ObjectNode schemasNode) throws IOException {
// Generate entities schema
Set<String> aspectDefinitions = nodesList.stream()
.map(nl -> nl.get("definitions").fieldNames())
.flatMap(it -> StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false))
.collect(Collectors.toSet());
withWrappedAspects(schemasNode, aspectDefinitions);
// Add entity schema
Set<String> entitySchema = withEntitySchema(schemasNode, aspectDefinitions);
// Write specific sections: components.* and paths
Set<String> modelDefinitions = Stream.concat(aspectDefinitions.stream(), entitySchema.stream())
.collect(Collectors.toSet());
// Just the component & parameters schema
Pair<ObjectNode, Set<String>> parameters = buildParameters(schemasNode, modelDefinitions);
ObjectNode componentsNode = writeComponentsYaml(schemasNode, parameters.left());
// Just the entity paths
writePathsYaml(modelDefinitions, parameters.right());
return componentsNode;
}
/**
* Convert the pdl model names to desired class names. Upper case first letter unless the 3rd character is upper case.
* i.e. mlModel -> MLModel
* dataset -> Dataset
* dataProduct -> DataProduct
* @param s input string
* @return class name
*/
public static String toUpperFirst(String s) {
if (s.length() > 2 && s.substring(2, 3).equals(s.substring(2, 3).toUpperCase())) {
return s.substring(0, 2).toUpperCase() + s.substring(2);
} else {
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
}
private Set<String> withEntitySchema(ObjectNode schemasNode, Set<String> definitions) {
return entityMap.values().stream()
// Make sure the primary key is defined
.filter(entity -> definitions.contains(toUpperFirst(entity.getKeyAspect())))
.filter(entity -> !ENTITY_EXCLUSIONS.contains(entity.getName()))
.map(entity -> {
final String upperName = toUpperFirst(entity.getName());
ObjectNode entityDefinitions = NODE_FACTORY.objectNode();
entityDefinitions.set(upperName + ENTITY_RESPONSE_SUFFIX, buildEntitySchema(entity, definitions, true));
entityDefinitions.set(upperName + ENTITY_REQUEST_SUFFIX, buildEntitySchema(entity, definitions, false));
entityDefinitions.set("Scroll" + upperName + ENTITY_RESPONSE_SUFFIX, buildEntityScrollSchema(entity));
schemasNode.setAll(entityDefinitions);
return upperName;
}).collect(Collectors.toSet());
}
private Set<String> withWrappedAspects(ObjectNode schemasNode, Set<String> aspects) {
return aspects.stream().peek(aspect -> {
ObjectNode aspectRef = NODE_FACTORY.objectNode()
.put("$ref", "#/definitions/" + aspect);
ObjectNode responseProperties = NODE_FACTORY.objectNode();
responseProperties.set("value", aspectRef);
responseProperties.set("systemMetadata", NODE_FACTORY.objectNode()
.put("description", "System metadata for the aspect.")
.put("$ref", "#/definitions/SystemMetadata"));
ObjectNode responseWrapper = NODE_FACTORY.objectNode()
.put("type", "object")
.put("description", "Aspect wrapper object.")
.set("properties", responseProperties);
responseWrapper.set("required", NODE_FACTORY.arrayNode().add("value"));
schemasNode.set(aspect + ASPECT_RESPONSE_SUFFIX, responseWrapper);
ObjectNode requestProperties = NODE_FACTORY.objectNode();
requestProperties.set("value", aspectRef);
ObjectNode requestWrapper = NODE_FACTORY.objectNode()
.put("type", "object")
.put("description", "Aspect wrapper object.")
.set("properties", requestProperties);
requestWrapper.set("required", NODE_FACTORY.arrayNode().add("value"));
schemasNode.set(aspect + ASPECT_REQUEST_SUFFIX, requestWrapper);
}).collect(Collectors.toSet());
}
private ObjectNode buildEntitySchema(Entity entity, Set<String> aspectDefinitions, boolean isResponse) {
ObjectNode propertiesNode = NODE_FACTORY.objectNode();
propertiesNode.set("urn", NODE_FACTORY.objectNode()
.put("description", "Unique id for " + entity.getName())
.put("type", "string"));
propertiesNode.set(entity.getKeyAspect(), buildAspectRef(entity.getKeyAspect(), isResponse));
entity.getAspects().stream()
.filter(aspect -> aspectDefinitions.contains(toUpperFirst(aspect))) // Only if aspect is defined
.forEach(aspect -> propertiesNode.set(aspect, buildAspectRef(aspect, isResponse)));
ObjectNode entityNode = NODE_FACTORY.objectNode()
.put("type", "object")
.put("description", Optional.ofNullable(entity.getDoc())
.orElse(toUpperFirst(entity.getName()) + " object."))
.set("properties", propertiesNode);
entityNode.set("required", NODE_FACTORY.arrayNode().add("urn"));
return entityNode;
}
private ObjectNode buildEntityScrollSchema(Entity entity) {
ObjectNode scrollResponsePropertiesNode = NODE_FACTORY.objectNode();
scrollResponsePropertiesNode.set("scrollId", NODE_FACTORY.objectNode()
.put("description", "Scroll id for pagination.")
.put("type", "string"));
scrollResponsePropertiesNode.set("entities", NODE_FACTORY.objectNode()
.put("description", Optional.ofNullable(entity.getDoc())
.orElse(toUpperFirst(entity.getName()) + " object."))
.put("type", "array")
.set("items", NODE_FACTORY.objectNode().put("$ref",
String.format("#/components/schemas/%s%s", toUpperFirst(entity.getName()), ENTITY_RESPONSE_SUFFIX))));
ObjectNode scrollResponseNode = NODE_FACTORY.objectNode()
.put("type", "object")
.put("description", "Scroll across " + toUpperFirst(entity.getName()) + " objects.")
.set("properties", scrollResponsePropertiesNode);
scrollResponseNode.set("required", NODE_FACTORY.arrayNode().add("entities"));
return scrollResponseNode;
}
private ObjectNode buildAspectRef(String aspect, boolean withSystemMetadata) {
if (withSystemMetadata) {
return NODE_FACTORY.objectNode()
.put("$ref", String.format("#/definitions/%s%s", toUpperFirst(aspect), ASPECT_RESPONSE_SUFFIX));
} else {
return NODE_FACTORY.objectNode()
.put("$ref", String.format("#/definitions/%s%s", toUpperFirst(aspect), ASPECT_REQUEST_SUFFIX));
}
}
private Optional<Pair<String, ObjectNode>> generateEntityParameters(final Entity entity, Set<String> definitions) {
/*
If not missing key
*/
if (definitions.contains(toUpperFirst(entity.getKeyAspect()))) {
final String parameterName = toUpperFirst(entity.getName()) + "Aspects";
ArrayNode aspects = NODE_FACTORY.arrayNode();
entity.getAspects().stream()
.filter(aspect -> definitions.contains(toUpperFirst(aspect))) // Only if aspect is defined
.distinct()
.forEach(aspects::add);
if (aspects.isEmpty()) {
aspects.add(entity.getKeyAspect());
}
ObjectNode itemsNode = NODE_FACTORY.objectNode()
.put("type", "string");
itemsNode.set("enum", aspects);
itemsNode.set("default", aspects);
ObjectNode schemaNode = NODE_FACTORY.objectNode()
.put("type", "array")
.set("items", itemsNode);
ObjectNode parameterSchemaNode = NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "aspects")
.put("explode", true)
.put("description", "Aspects to include in response.")
.set("schema", schemaNode);
parameterSchemaNode.set("example", aspects);
ObjectNode parameterNode = NODE_FACTORY.objectNode()
.set(parameterName + MODEL_VERSION, parameterSchemaNode);
return Optional.of(Pair.of(parameterName, parameterNode));
}
return Optional.empty();
}
private Pair<ObjectNode, Set<String>> buildParameters(ObjectNode schemasNode, Set<String> definitions) {
ObjectNode parametersNode = NODE_FACTORY.objectNode();
Set<String> parameterDefinitions = entityMap.values().stream()
.flatMap(entity -> generateEntityParameters(entity, definitions).stream())
.map(entityNode -> {
parametersNode.setAll(entityNode.right());
return entityNode.left();
})
.collect(Collectors.toSet());
return Pair.of(extraParameters(parametersNode), parameterDefinitions);
}
private ObjectNode writeComponentsYaml(ObjectNode schemasNode, ObjectNode parametersNode) throws IOException {
ObjectNode componentsNode = NODE_FACTORY.objectNode();
componentsNode.set("schemas", schemasNode);
componentsNode.set("parameters", extraParameters(parametersNode));
ObjectNode componentsDocNode = NODE_FACTORY.objectNode().set("components", componentsNode);
final String componentsYaml = new YAMLMapper().writeValueAsString(componentsDocNode)
.replaceAll("definitions", "components/schemas")
.replaceAll("\n\\s+description: null", "")
.replaceAll("\n\\s+- type: \"null\"", "");
Files.write(Paths.get(combinedDirectory + GenerateJsonSchemaTask.sep + "open-api-components.yaml"),
componentsYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
return componentsDocNode;
}
private ObjectNode extraParameters(ObjectNode parametersNode) {
parametersNode.set("ScrollId" + MODEL_VERSION, NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "scrollId")
.put("description", "Scroll pagination token.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "string")));
ArrayNode sortFields = NODE_FACTORY.arrayNode();
sortFields.add("urn");
ObjectNode sortFieldsNode = NODE_FACTORY.objectNode()
.put("type", "string");
sortFieldsNode.set("enum", sortFields);
sortFieldsNode.set("default", sortFields.get(0));
ObjectNode sortFieldsSchemaNode = NODE_FACTORY.objectNode()
.put("type", "array")
.put("default", "urn")
.set("items", sortFieldsNode);
parametersNode.set("SortBy" + MODEL_VERSION, NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "sort")
.put("explode", true)
.put("description", "Sort fields for pagination.")
.put("example", "urn")
.set("schema", sortFieldsSchemaNode));
parametersNode.set("SortOrder" + MODEL_VERSION, NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "sortOrder")
.put("explode", true)
.put("description", "Sort direction field for pagination.")
.put("example", "ASCENDING")
.set("schema", NODE_FACTORY.objectNode()
.put("default", "ASCENDING")
.put("$ref", "#/components/schemas/SortOrder")));
parametersNode.set("PaginationCount" + MODEL_VERSION, NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "count")
.put("description", "Number of items per page.")
.put("example", "10")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "integer")
.put("default", 10)
.put("minimum", 1)));
parametersNode.set("ScrollQuery" + MODEL_VERSION, NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "query")
.put("description", "Structured search query.")
.put("example", "*")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "string")
.put("default", "*")));
return parametersNode;
}
private void writePathsYaml(Set<String> modelDefinitions, Set<String> parameterDefinitions) throws IOException {
ObjectNode pathsNode = NODE_FACTORY.objectNode();
entityMap.values().stream()
.filter(e -> modelDefinitions.contains(toUpperFirst(e.getName())))
.forEach(entity -> {
pathsNode.set(String.format("/%s", entity.getName().toLowerCase()),
buildListEntityPath(entity, parameterDefinitions));
pathsNode.set(String.format("/%s/{urn}", entity.getName().toLowerCase()),
buildSingleEntityPath(entity, parameterDefinitions));
});
buildEntityAspectPaths(pathsNode, modelDefinitions);
ObjectNode pathsDocNode = NODE_FACTORY.objectNode().set("paths", pathsNode);
final String componentsYaml = new YAMLMapper().writeValueAsString(pathsDocNode)
.replaceAll("\n\\s+- type: \"null\"", "")
.replaceAll("\n\\s+description: null", "");
Files.write(Paths.get(combinedDirectory + GenerateJsonSchemaTask.sep + "open-api-paths.yaml"),
componentsYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING);
}
private void buildEntityAspectPaths(ObjectNode pathsNode, Set<String> modelDefinitions) {
entityMap.values().stream()
.filter(e -> modelDefinitions.contains(toUpperFirst(e.getName())))
.forEach(entity -> {
entity.getAspects().stream()
.filter(aspect -> SUPPORTED_ASPECT_PATHS.contains(aspect))
.filter(aspect -> modelDefinitions.contains(toUpperFirst(aspect)))
.forEach(aspect -> pathsNode.set(String.format("/%s/{urn}/%s",
entity.getName().toLowerCase(), aspect.toLowerCase()),
buildSingleEntityAspectPath(entity, aspect)));
});
}
private ObjectNode buildListEntityPath(Entity entity, Set<String> parameterDefinitions) {
final String upperFirst = toUpperFirst(entity.getName());
final String aspectParameterName = upperFirst + "Aspects";
ArrayNode tagsNode = NODE_FACTORY.arrayNode()
.add(entity.getName() + " Entity");
ObjectNode scrollMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("Scroll %s.", upperFirst))
.put("operationId", String.format("scroll", upperFirst));
ArrayNode scrollPathParametersNode = NODE_FACTORY.arrayNode();
scrollMethod.set("parameters", scrollPathParametersNode);
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "systemMetadata")
.put("description", "Include systemMetadata with response.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
if (parameterDefinitions.contains(aspectParameterName)) {
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", String.format("#/components/parameters/%s", aspectParameterName + MODEL_VERSION)));
}
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", "#/components/parameters/PaginationCount" + MODEL_VERSION));
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", "#/components/parameters/ScrollId" + MODEL_VERSION));
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", "#/components/parameters/SortBy" + MODEL_VERSION));
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", "#/components/parameters/SortOrder" + MODEL_VERSION));
scrollPathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", "#/components/parameters/ScrollQuery" + MODEL_VERSION));
scrollMethod.set("parameters", scrollPathParametersNode);
scrollMethod.set("responses", NODE_FACTORY.objectNode()
.set("200", NODE_FACTORY.objectNode().put("description", "Success")
.set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode()
.put("$ref", String.format("#/components/schemas/Scroll%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX)))))));
scrollMethod.set("tags", tagsNode);
ObjectNode postMethod = NODE_FACTORY.objectNode()
.put("summary", "Create " + upperFirst)
.put("operationId", String.format("create", upperFirst));
ArrayNode postParameters = NODE_FACTORY.arrayNode();
postMethod.set("parameters", postParameters);
postParameters.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "createIfNotExists")
.put("description", "Create the aspect if it does not already exist.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
postParameters.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "createEntityIfNotExists")
.put("description", "Create the entity ONLY if it does not already exist. Fails in case when the entity exists.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
postMethod.set("requestBody", NODE_FACTORY.objectNode()
.put("description", "Create " + entity.getName() + " entities.")
.put("required", true)
.set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode().put("type", "array")
.set("items", NODE_FACTORY.objectNode().put("$ref",
String.format("#/components/schemas/%s%s", upperFirst, ENTITY_REQUEST_SUFFIX)))))));
postMethod.set("responses", NODE_FACTORY.objectNode()
.set("201", NODE_FACTORY.objectNode().put("description", "Create " + entity.getName() + " entities.")
.set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode().put("type", "array")
.set("items", NODE_FACTORY.objectNode().put("$ref",
String.format("#/components/schemas/%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX))))))));
postMethod.set("tags", tagsNode);
ObjectNode listMethods = NODE_FACTORY.objectNode();
listMethods.set("get", scrollMethod);
listMethods.set("post", postMethod);
return listMethods;
}
private ObjectNode buildSingleEntityPath(Entity entity, Set<String> parameterDefinitions) {
final String upperFirst = toUpperFirst(entity.getName());
final String aspectParameterName = upperFirst + "Aspects";
ArrayNode tagsNode = NODE_FACTORY.arrayNode().add(entity.getName() + " Entity");
ObjectNode getMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("Get %s by key.", entity.getName()))
.put("operationId", String.format("get", upperFirst));
getMethod.set("tags", tagsNode);
ArrayNode singlePathParametersNode = NODE_FACTORY.arrayNode();
getMethod.set("parameters", singlePathParametersNode);
singlePathParametersNode.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "systemMetadata")
.put("description", "Include systemMetadata with response.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
if(parameterDefinitions.contains(aspectParameterName)) {
singlePathParametersNode.add(NODE_FACTORY.objectNode()
.put("$ref", String.format("#/components/parameters/%s", aspectParameterName + MODEL_VERSION)));
}
ObjectNode responses = NODE_FACTORY.objectNode();
getMethod.set("responses", responses);
responses.set("200", NODE_FACTORY.objectNode().put("description", "Success")
.set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode().put("$ref",
String.format("#/components/schemas/%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX))))));
responses.set("404", NODE_FACTORY.objectNode()
.put("description", "Not Found")
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode()))));
ObjectNode headResponses = NODE_FACTORY.objectNode();
headResponses.set("204", NODE_FACTORY.objectNode()
.put("description", entity.getName() + " exists.")
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode())));
headResponses.set("404", NODE_FACTORY.objectNode()
.put("description", entity.getName() + " does not exist.")
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode())));
ObjectNode headMethod = NODE_FACTORY.objectNode()
.put("summary", upperFirst + " existence.")
.put("operationId", String.format("head", upperFirst))
.set("responses", headResponses);
headMethod.set("tags", tagsNode);
ObjectNode deleteMethod = NODE_FACTORY.objectNode()
.put("summary", "Delete entity " + upperFirst)
.put("operationId", String.format("delete", upperFirst))
.set("responses", NODE_FACTORY.objectNode()
.set("200", NODE_FACTORY.objectNode()
.put("description", "Delete " + entity.getName() + " entity.")
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode()))));
deleteMethod.set("tags", tagsNode);
ObjectNode singlePathMethods = NODE_FACTORY.objectNode()
.set("parameters", NODE_FACTORY.arrayNode()
.add(NODE_FACTORY.objectNode()
.put("in", "path")
.put("name", "urn")
.put("required", true)
.set("schema", NODE_FACTORY.objectNode().put("type", "string"))));
singlePathMethods.set("get", getMethod);
singlePathMethods.set("head", headMethod);
singlePathMethods.set("delete", deleteMethod);
return singlePathMethods;
}
private ObjectNode buildSingleEntityAspectPath(Entity entity, String aspect) {
final String upperFirstEntity = toUpperFirst(entity.getName());
final String upperFirstAspect = toUpperFirst(aspect);
ArrayNode tagsNode = NODE_FACTORY.arrayNode()
.add(aspect + " Aspect");
ObjectNode getMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("Get %s for %s.", aspect, entity.getName()))
.put("operationId", String.format("get%s", upperFirstAspect));
getMethod.set("tags", tagsNode);
ArrayNode singlePathParametersNode = NODE_FACTORY.arrayNode();
getMethod.set("parameters", singlePathParametersNode);
singlePathParametersNode.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "systemMetadata")
.put("description", "Include systemMetadata with response.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
getMethod.set("responses", NODE_FACTORY.objectNode().set("200", NODE_FACTORY.objectNode()
.put("description", "Success").set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode().set("schema", NODE_FACTORY.objectNode()
.put("$ref",
String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_RESPONSE_SUFFIX)))))));
ObjectNode headResponses = NODE_FACTORY.objectNode();
headResponses.set("200", NODE_FACTORY.objectNode()
.put("description", String.format("%s on %s exists.", aspect, entity.getName()))
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode())));
headResponses.set("404", NODE_FACTORY.objectNode()
.put("description", String.format("%s on %s does not exist.", aspect, entity.getName()))
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode())));
ObjectNode headMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("%s on %s existence.", aspect, upperFirstEntity))
.put("operationId", String.format("head%s", upperFirstAspect))
.set("responses", headResponses);
headMethod.set("tags", tagsNode);
ObjectNode deleteMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("Delete %s on entity %s", aspect, upperFirstEntity))
.put("operationId", String.format("delete%s", upperFirstAspect))
.set("responses", NODE_FACTORY.objectNode()
.set("200", NODE_FACTORY.objectNode()
.put("description", String.format("Delete %s on %s entity.", aspect, upperFirstEntity))
.set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode()))));
deleteMethod.set("tags", tagsNode);
ObjectNode postMethod = NODE_FACTORY.objectNode()
.put("summary", String.format("Create aspect %s on %s ", aspect, upperFirstEntity))
.put("operationId", String.format("create%s", upperFirstAspect));
ArrayNode postParameters = NODE_FACTORY.arrayNode();
postMethod.set("parameters", postParameters);
postParameters.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "createIfNotExists")
.put("description", "Create the aspect if it does not already exist.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
postParameters.add(NODE_FACTORY.objectNode()
.put("in", "query")
.put("name", "createEntityIfNotExists")
.put("description", "Create the entity if it does not already exist. Fails in case when the entity exists.")
.set("schema", NODE_FACTORY.objectNode()
.put("type", "boolean")
.put("default", false)));
postMethod.set("requestBody", NODE_FACTORY.objectNode()
.put("description", String.format("Create aspect %s on %s entity.", aspect, upperFirstEntity))
.put("required", true).set("content", NODE_FACTORY.objectNode()
.set("application/json", NODE_FACTORY.objectNode().set("schema", NODE_FACTORY.objectNode()
.put("$ref",
String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_REQUEST_SUFFIX))))));
postMethod.set("responses", NODE_FACTORY.objectNode().set("201", NODE_FACTORY.objectNode()
.put("description", String.format("Create aspect %s on %s entity.", aspect, upperFirstEntity))
.set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode()
.set("schema", NODE_FACTORY.objectNode().put("$ref",
String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_RESPONSE_SUFFIX)))))));
postMethod.set("tags", tagsNode);
ObjectNode singlePathMethods = NODE_FACTORY.objectNode()
.set("parameters", NODE_FACTORY.arrayNode()
.add(NODE_FACTORY.objectNode()
.put("in", "path")
.put("name", "urn")
.put("required", true)
.set("schema", NODE_FACTORY.objectNode().put("type", "string"))));
singlePathMethods.set("get", getMethod);
singlePathMethods.set("head", headMethod);
singlePathMethods.set("delete", deleteMethod);
singlePathMethods.set("post", postMethod);
return singlePathMethods;
}
}