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

Commit

Permalink
fix: better support of swagger mock generation
Browse files Browse the repository at this point in the history
  • Loading branch information
aelamrani authored and NicolasGeraud committed May 29, 2019
1 parent 08a9f2c commit 18bbe53
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 92 deletions.
Expand Up @@ -26,9 +26,8 @@ public class SwaggerVerb {
private String verb;
private String description;
private String responseStatus;
private String responseType;
private Map<String, Object> responseProperties;
private Object responseExample;
private boolean array;

public String getVerb() {
return verb;
Expand All @@ -54,14 +53,6 @@ public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}

public String getResponseType() {
return responseType;
}

public void setResponseType(String responseType) {
this.responseType = responseType;
}

public Map<String, Object> getResponseProperties() {
return responseProperties;
}
Expand All @@ -70,11 +61,11 @@ public void setResponseProperties(Map<String, Object> responseProperties) {
this.responseProperties = responseProperties;
}

public Object getResponseExample() {
return responseExample;
public boolean isArray() {
return array;
}

public void setResponseExample(Object responseExample) {
this.responseExample = responseExample;
public void setArray(boolean array) {
this.array = array;
}
}
Expand Up @@ -63,15 +63,13 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.CollectionUtils;

import javax.xml.bind.DatatypeConverter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.gravitee.management.model.EventType.PUBLISH_API;
Expand Down Expand Up @@ -262,10 +260,10 @@ private ApiEntity create(final NewApiEntity newApiEntity, final String userId,
header.put("value", "application/json");
configuration.put("headers", singletonList(header));
try {
if (swaggerVerb.getResponseType() != null || swaggerVerb.getResponseExample() != null) {
final Object mockContent = swaggerVerb.getResponseExample() == null ?
generateMockContent(swaggerVerb.getResponseType(), swaggerVerb.getResponseProperties()) : swaggerVerb.getResponseExample();
configuration.put("content", objectMapper.writeValueAsString(mockContent));
final Map<String, Object> responseProperties = swaggerVerb.getResponseProperties();
if (responseProperties != null) {
configuration.put("content", objectMapper.writeValueAsString(swaggerVerb.isArray()?
singletonList(responseProperties): responseProperties));
}
policy.setConfiguration(objectMapper.writeValueAsString(configuration));
} catch (final JsonProcessingException e) {
Expand Down Expand Up @@ -321,37 +319,6 @@ private String addGraviteeUrl(String apiContextPath, String payload) {
return swaggerService.replaceServerList(payload, graviteeUrls);
}

private Object generateMockContent(final String responseType, final Map<String, Object> responseProperties) {
final Random random = new Random();
switch (responseType) {
case "string":
return "Mocked " + (responseProperties == null ? "response" : responseProperties.getOrDefault("key", "response"));
case "boolean":
return random.nextBoolean();
case "integer":
return random.nextInt(1000);
case "number":
return random.nextDouble();
case "array":
return responseProperties == null ? emptyList() : singletonList(generateMockContent("object", responseProperties));
case "object":
if (responseProperties == null) {
return emptyMap();
}
final Map<String, Object> mock = new HashMap<>(responseProperties.size());
responseProperties.forEach((k, v) -> {
if (v instanceof Map) {
mock.put(k, generateMockContent("object", (Map) v));
} else {
mock.put(k, generateMockContent((String) v, singletonMap("key", k)));
}
});
return mock;
default:
return emptyMap();
}
}

private ApiEntity create0(UpdateApiEntity api, String userId) throws ApiAlreadyExistsException {
try {
LOGGER.debug("Create {} for user {}", api, userId);
Expand Down
Expand Up @@ -37,6 +37,7 @@
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
Expand Down Expand Up @@ -67,7 +68,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Collections.emptyMap;
import static java.util.Collections.*;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toMap;

Expand Down Expand Up @@ -328,26 +329,23 @@ private NewSwaggerApiEntity mapSwagger12ToNewApi(final Swagger swagger, final bo
if (responseSchema != null) {
if (responseSchema instanceof ArrayModel) {
final ArrayModel arrayModel = (ArrayModel) responseSchema;
swaggerVerb.setResponseType(arrayModel.getType());
swaggerVerb.setArray(true);
if (arrayModel.getItems() instanceof RefProperty) {
final String simpleRef = ((RefProperty) arrayModel.getItems()).getSimpleRef();
swaggerVerb.setResponseProperties(getResponseFromSimpleRef(swagger, simpleRef));
} else if (arrayModel.getItems() instanceof ObjectProperty) {
swaggerVerb.setResponseProperties(getResponseProperties(swagger, ((ObjectProperty) arrayModel.getItems()).getProperties()));
}
} else if (responseSchema instanceof RefModel) {
swaggerVerb.setResponseType("object");
final String simpleRef = ((RefModel) responseSchema).getSimpleRef();
swaggerVerb.setResponseProperties(getResponseFromSimpleRef(swagger, simpleRef));
} else if (responseSchema instanceof ModelImpl) {
final ModelImpl model = (ModelImpl) responseSchema;
swaggerVerb.setResponseType(model.getType());
swaggerVerb.setArray("array".equals(model.getType()));
if ("object".equals(model.getType())) {
if (model.getAdditionalProperties() != null) {
swaggerVerb.setResponseProperties(Collections.singletonMap("additionalProperty", model.getAdditionalProperties().getType()));
}
} else {
swaggerVerb.setResponseType(model.getType());
}
}
}
Expand Down Expand Up @@ -490,9 +488,10 @@ private SwaggerVerb getSwaggerVerb(final SwaggerParseResult swagger, final Opera
final io.swagger.v3.oas.models.media.MediaType mediaType =
responseEntry.getValue().getContent().entrySet().iterator().next().getValue();
if (mediaType.getExample() != null) {
swaggerVerb.setResponseExample(mapper.convertValue(mediaType.getExample(), Map.class));
swaggerVerb.setResponseProperties(mapper.convertValue(mediaType.getExample(), Map.class));
} else if (mediaType.getExamples() != null) {
swaggerVerb.setResponseExample(mediaType.getExamples().entrySet().iterator().next().getValue().getValue());
final Entry<String, Example> next = mediaType.getExamples().entrySet().iterator().next();
swaggerVerb.setResponseProperties(singletonMap(next.getKey(), next.getValue().getValue()));
} else {
final Schema responseSchema = mediaType.getSchema();
if (responseSchema != null) {
Expand All @@ -511,34 +510,57 @@ private SwaggerVerb getSwaggerVerb(final SwaggerParseResult swagger, final Opera

private void processResponseSchema(SwaggerParseResult swagger, SwaggerVerb swaggerVerb, String type, Schema responseSchema) {
if (responseSchema.getProperties() == null) {
swaggerVerb.setResponseType(type);
swaggerVerb.setArray("array".equals(type));
if (responseSchema.getAdditionalProperties() != null) {
swaggerVerb.setResponseProperties(Collections.singletonMap("additionalProperty", ((ObjectSchema) responseSchema.getAdditionalProperties()).getType()));
} else if (responseSchema.get$ref() != null) {
if (!"array".equals(type)) {
final String typeByRef = getTypeByRef(swagger, responseSchema.get$ref());
if (typeByRef != null) {
swaggerVerb.setResponseType(typeByRef);
}
swaggerVerb.setArray(isRefArray(swagger, responseSchema.get$ref()));
}
swaggerVerb.setResponseProperties(getResponseFromSimpleRef(swagger, responseSchema.get$ref()));
} else {
swaggerVerb.setResponseProperties(singletonMap(responseSchema.getType(), getResponsePropertiesFromType(responseSchema.getType())));
}
} else {
swaggerVerb.setResponseExample(getResponseExample(responseSchema.getProperties()));
swaggerVerb.setResponseProperties(getResponseExample(responseSchema.getProperties()));
}
}

private String getTypeByRef(SwaggerParseResult swagger, String ref) {
private boolean isRefArray(SwaggerParseResult swagger, final String ref) {
final String simpleRef = ref.substring(ref.lastIndexOf('/') + 1);
return swagger.getOpenAPI().getComponents().getSchemas().get(simpleRef).getType();
final Schema schema = swagger.getOpenAPI().getComponents().getSchemas().get(simpleRef);
return schema instanceof ArraySchema;
}

private Object getResponsePropertiesFromType(final String responseType) {
final Random random = new Random();
switch (responseType) {
case "string":
return "Mocked string";
case "boolean":
return random.nextBoolean();
case "integer":
return random.nextInt(1000);
case "number":
return random.nextDouble();
case "array":
return singletonList(getResponsePropertiesFromType("string"));
default:
return emptyMap();
}
}

private Map<String, Object> getResponseFromSimpleRef(SwaggerParseResult swagger, String ref) {
final String simpleRef = ref.substring(ref.lastIndexOf('/') + 1);
final Schema schema = swagger.getOpenAPI().getComponents().getSchemas().get(simpleRef);

if (schema instanceof ArraySchema) {
return getResponseFromSimpleRef(swagger, ((ArraySchema) schema).getItems().get$ref());
final Schema<?> items = ((ArraySchema) schema).getItems();
if (items.get$ref() != null) {
return getResponseFromSimpleRef(swagger, items.get$ref());
} else {
return singletonMap(items.getType(), singletonList(items.getExample()));
}
} else if (schema instanceof ComposedSchema) {
final Map<String, Object> response = new HashMap<>();
((ComposedSchema) schema).getAllOf().forEach(composedSchema -> {
Expand All @@ -560,10 +582,32 @@ private Map<String, Object> getResponseFromSimpleRef(SwaggerParseResult swagger,

private Map<String, Object> getResponseProperties(final SwaggerParseResult swagger, final Map<String, Schema> properties) {
return properties.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> {
if (e.getValue().getType() != null) {
return e.getValue().getType();
final String type = e.getValue().getType();
if (type != null) {
final Object example = e.getValue().getExample();
if (example == null) {
final List enums = e.getValue().getEnum();
if (enums == null) {
if (type.equals("object")) {
return getResponseProperties(swagger, e.getValue().getProperties());
} else if (type.equals("array")) {
return singletonList(((ArraySchema) e.getValue()).getItems().getExample());
}
return getResponsePropertiesFromType(type);
} else {
return enums.get(0);
}
} else {
return example;
}
} else {
return getResponseFromSimpleRef(swagger, e.getValue().get$ref());
final String simpleRef = e.getValue().get$ref().substring(e.getValue().get$ref().lastIndexOf('/') + 1);
final Schema schema = swagger.getOpenAPI().getComponents().getSchemas().get(simpleRef);
if (schema instanceof ArraySchema) {
return singletonList(((ArraySchema) schema).getItems().getExample());
} else {
return getResponseFromSimpleRef(swagger, e.getValue().get$ref());
}
}
}));
}
Expand Down

0 comments on commit 18bbe53

Please sign in to comment.