Skip to content
This repository has been archived by the owner on Aug 8, 2018. It is now read-only.

Use external model references instead of inlining #81

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
Expand All @@ -39,15 +40,15 @@ public class SchemaTransformer {

/**
* Get a schema schema in "flattened" form whereby all dependent references are resolved
* and included as inline schema definitions
* and included as external schema definitions
*
* @return the json-schema string in flattened form
*/
public String flatten(String model, String models) {
return getFlattened(deserialize(model), deserialize(models));
public String flatten(String apiId, String model, String models) {
return getFlattened(apiId, deserialize(model), deserialize(models));
}

private void buildSchemaReferenceMap(JsonNode model, JsonNode models, Map<String, String> modelMap) {
private void buildSchemaReferenceMap(String apiId, JsonNode model, JsonNode models, Map<String, String> modelMap) {
Map<JsonNode, JsonNode> refs = new HashMap<>();
findReferences(model, refs);

Expand All @@ -58,10 +59,10 @@ private void buildSchemaReferenceMap(JsonNode model, JsonNode models, Map<String

JsonNode subSchema = getSchema(schemaName, models);

// replace reference values with inline definitions
replaceRef((ObjectNode) refs.get(ref), schemaName);
// replace reference values with external definitions
replaceRef(apiId, (ObjectNode) refs.get(ref), schemaName);

buildSchemaReferenceMap(subSchema, models, modelMap);
buildSchemaReferenceMap(apiId, subSchema, models, modelMap);

modelMap.put(schemaName, serializeExisting(subSchema));
}
Expand All @@ -71,12 +72,10 @@ private JsonNode getSchema(String schemaName, JsonNode models) {
return models.findPath(schemaName);
}

private String getFlattened(JsonNode model, JsonNode models) {
private String getFlattened(String apiId, JsonNode model, JsonNode models) {
HashMap<String, String> schemaMap = new HashMap<>();

buildSchemaReferenceMap(model, models, schemaMap);

replaceRefs(model, schemaMap);
buildSchemaReferenceMap(apiId, model, models, schemaMap);

if (LOG.isTraceEnabled()) {
try {
Expand Down Expand Up @@ -108,26 +107,12 @@ private void validate(JsonNode rootNode) {
}
}

/*
* Add schema references as inline definitions to the root schema
*/
private void replaceRefs(JsonNode root, HashMap<String, String> schemaMap) {

ObjectNode definitionsNode = new ObjectNode(JsonNodeFactory.instance);

for (Map.Entry<String, String> entry : schemaMap.entrySet()) {
JsonNode schemaNode = deserialize(entry.getValue());
definitionsNode.set(entry.getKey(), schemaNode);
}

((ObjectNode)root).set("definitions", definitionsNode);
}

/*
* Replace a reference node with an inline reference
*/
private void replaceRef(ObjectNode parent, String schemaName) {
parent.set("$ref", new TextNode("#/definitions/" + schemaName));
private void replaceRef(String apiId, ObjectNode parent, String schemaName) {
// parent.set("$ref", new TextNode("#/definitions/" + schemaName));
parent.set("$ref", new TextNode("https://apigateway.amazonaws.com/restapis/" + apiId + "/models/" + schemaName));
}

/*
Expand Down Expand Up @@ -163,7 +148,7 @@ JsonNode deserialize(String schemaText) {
*/
private String serializeExisting(JsonNode root) {
try {
return new ObjectMapper().writeValueAsString(root);
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(root);
} catch (JsonProcessingException e) {
throw new IllegalStateException("Could not serialize generated schema json", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ private void createModels(RestApi api, Map<String, com.wordnik.swagger.models.Mo
private void createModel(RestApi api, String modelName, com.wordnik.swagger.models.Model model, Map<String, com.wordnik.swagger.models.Model> definitions, String modelContentType) {
LOG.info(format("Creating model for api id %s with name %s", api.getId(), modelName));

createModel(api, modelName, model.getDescription(), generateSchema(model, modelName, definitions), modelContentType);
createModel(api, modelName, model.getDescription(), generateSchema(api, model, modelName, definitions), modelContentType);
}

private void createModel(RestApi api, String modelName, Property model, String modelContentType) {
LOG.info(format("Creating model for api id %s with name %s", api.getId(), modelName));

createModel(api, modelName, model.getDescription(), generateSchema(model, modelName, swagger.getDefinitions()), modelContentType);
createModel(api, modelName, model.getDescription(), generateSchema(api, model, modelName, swagger.getDefinitions()), modelContentType);
}

private void updateMethods(RestApi api, String basePath, Map<String, Path> paths, List<String> apiProduces) {
Expand Down Expand Up @@ -320,17 +320,17 @@ private Boolean isApiKeyRequired(Operation op) {
return false;
}

private String generateSchema(Property model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
return generateSchemaString(model, modelName, definitions);
private String generateSchema(RestApi api, Property model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
return generateSchemaString(api, model, modelName, definitions);
}

private String generateSchemaString(Object model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
private String generateSchemaString(RestApi api, Object model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
try {
String modelSchema = Json.mapper().writeValueAsString(model);
String models = Json.mapper().writeValueAsString(definitions);

// inline all references
String schema = new SchemaTransformer().flatten(modelSchema, models);
String schema = new SchemaTransformer().flatten(api.getId(), modelSchema, models);

LOG.info("Generated json-schema for model " + modelName + ": " + schema);

Expand All @@ -340,8 +340,8 @@ private String generateSchemaString(Object model, String modelName, Map<String,
}
}

private String generateSchema(com.wordnik.swagger.models.Model model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
return generateSchemaString(model, modelName, definitions);
private String generateSchema(RestApi api, com.wordnik.swagger.models.Model model, String modelName, Map<String, com.wordnik.swagger.models.Model> definitions) {
return generateSchemaString(api, model, modelName, definitions);
}

private Optional<String> getInputModel(BodyParameter p) {
Expand Down Expand Up @@ -400,7 +400,7 @@ private void updateModels(RestApi api, Map<String, com.wordnik.swagger.models.Mo

private void updateModel(RestApi api, String modelName, com.wordnik.swagger.models.Model model) {
LOG.info(format("Updating model for api id %s and model name %s", api.getId(), modelName));
updateModel(api, modelName, generateSchema(model, modelName, swagger.getDefinitions()));
updateModel(api, modelName, generateSchema(api, model, modelName, swagger.getDefinitions()));
}

private void updateMethod(RestApi api, Resource resource, String httpMethod, Operation op, String modelContentType) {
Expand Down