Skip to content
Merged
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
@@ -1,5 +1,8 @@
package io.swagger.codegen.examples;

import static io.swagger.models.properties.StringProperty.Format.URI;
import static io.swagger.models.properties.StringProperty.Format.URL;

import io.swagger.models.Model;
import io.swagger.models.ModelImpl;
import io.swagger.models.properties.ArrayProperty;
Expand All @@ -11,7 +14,6 @@
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FileProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.ObjectProperty;
Expand All @@ -20,71 +22,107 @@
import io.swagger.models.properties.StringProperty;
import io.swagger.models.properties.UUIDProperty;
import io.swagger.util.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ExampleGenerator {
private static final Logger logger = LoggerFactory.getLogger(ExampleGenerator.class);

// TODO: move constants to more appropriate location
private static final String MIME_TYPE_JSON = "application/json";
private static final String MIME_TYPE_XML = "application/xml";

private static final String EXAMPLE = "example";
private static final String CONTENT_TYPE = "contentType";
private static final String OUTPUT = "output";
private static final String NONE = "none";

protected Map<String, Model> examples;

public ExampleGenerator(Map<String, Model> examples) {
this.examples = examples;
}

public List<Map<String, String>> generate(Map<String, Object> examples, List<String> mediaTypes, Property property) {
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
Set<String> processedModels = new HashSet<String>();
List<Map<String, String>> output = new ArrayList<>();
Set<String> processedModels = new HashSet<>();
if (examples == null) {
if (mediaTypes == null) {
// assume application/json for this
mediaTypes = Arrays.asList("application/json"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
mediaTypes = Collections.singletonList(MIME_TYPE_JSON); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
}
for (String mediaType : mediaTypes) {
Map<String, String> kv = new HashMap<String, String>();
kv.put("contentType", mediaType);
if (property != null && mediaType.startsWith("application/json")) {
Map<String, String> kv = new HashMap<>();
kv.put(CONTENT_TYPE, mediaType);
if (property != null && mediaType.startsWith(MIME_TYPE_JSON)) {
String example = Json.pretty(resolvePropertyToExample(mediaType, property, processedModels));

if (example != null) {
kv.put("example", example);
kv.put(EXAMPLE, example);
output.add(kv);
}
} else if (property != null && mediaType.startsWith("application/xml")) {
} else if (property != null && mediaType.startsWith(MIME_TYPE_XML)) {
String example = new XmlExampleGenerator(this.examples).toXml(property);
if (example != null) {
kv.put("example", example);
kv.put(EXAMPLE, example);
output.add(kv);
}
}
}
} else {
for (Map.Entry<String, Object> entry : examples.entrySet()) {
final Map<String, String> kv = new HashMap<String, String>();
kv.put("contentType", entry.getKey());
kv.put("example", Json.pretty(entry.getValue()));
final Map<String, String> kv = new HashMap<>();
kv.put(CONTENT_TYPE, entry.getKey());
kv.put(EXAMPLE, Json.pretty(entry.getValue()));
output.add(kv);
}
}
if (output.size() == 0) {
Map<String, String> kv = new HashMap<String, String>();
kv.put("output", "none");
Map<String, String> kv = new HashMap<>();
kv.put(OUTPUT, NONE);
output.add(kv);
}
return output;
}

protected Object resolvePropertyToExample(String mediaType, Property property, Set<String> processedModels) {
private Object resolvePropertyToExample(String mediaType, Property property, Set<String> processedModels) {
logger.debug("Resolving example for property {}...", property);
if (property.getExample() != null) {
logger.debug("Example set in swagger spec, returning example: '{}'", property.getExample().toString());
return property.getExample();
} else if (property instanceof StringProperty) {
logger.debug("String property");
String defaultValue = ((StringProperty) property).getDefault();
if (defaultValue != null && !defaultValue.isEmpty()) {
logger.debug("Default value found: '{}'", defaultValue);
return defaultValue;
}
List<String> enumValues = ((StringProperty) property).getEnum();
if (enumValues != null && !enumValues.isEmpty()) {
logger.debug("Enum value found: '{}'", enumValues.get(0));
return enumValues.get(0);
}
String format = property.getFormat();
if (format != null && (URI.getName().equals(format) || URL.getName().equals(format))) {
logger.debug("URI or URL format, without default or enum, generating random one.");
return "http://example.com/aeiou";
}
logger.debug("No values found, using default string 'aeiou' as example");
return "aeiou";
} else if (property instanceof BooleanProperty) {
Boolean defaultValue = ((BooleanProperty) property).getDefault();
if (defaultValue != null) {
return defaultValue;
}
return Boolean.TRUE;
} else if (property instanceof ArrayProperty) {
Property innerType = ((ArrayProperty) property).getItems();
Expand All @@ -97,21 +135,28 @@ protected Object resolvePropertyToExample(String mediaType, Property property, S
return "2000-01-23";
} else if (property instanceof DateTimeProperty) {
return "2000-01-23T04:56:07.000+00:00";
} else if (property instanceof DecimalProperty) {
return new BigDecimal(1.3579);
} else if (property instanceof DoubleProperty) {
return 3.149;
Double min = ((DecimalProperty) property).getMinimum() == null ? null : ((DecimalProperty) property).getMinimum().doubleValue();
Double max = ((DecimalProperty) property).getMaximum() == null ? null : ((DecimalProperty) property).getMaximum().doubleValue();
return randomNumber(min, max);
} else if (property instanceof FloatProperty) {
Double min = ((DecimalProperty) property).getMinimum() == null ? null : ((DecimalProperty) property).getMinimum().doubleValue();
Double max = ((DecimalProperty) property).getMaximum() == null ? null : ((DecimalProperty) property).getMaximum().doubleValue();
return (float) randomNumber(min, max);
} else if (property instanceof DecimalProperty) {
Double min = ((DecimalProperty) property).getMinimum() == null ? null : ((DecimalProperty) property).getMinimum().doubleValue();
Double max = ((DecimalProperty) property).getMaximum() == null ? null : ((DecimalProperty) property).getMaximum().doubleValue();
return new BigDecimal(randomNumber(min, max));
} else if (property instanceof FileProperty) {
return ""; // TODO
} else if (property instanceof FloatProperty) {
return 1.23f;
} else if (property instanceof IntegerProperty) {
return 123;
} else if (property instanceof LongProperty) {
return 123456789L;
// Properties that are not Integer or Long may still be BaseInteger
} else if (property instanceof BaseIntegerProperty) {
return 123;
Double min = ((BaseIntegerProperty) property).getMinimum() == null ? null : ((BaseIntegerProperty) property).getMinimum().doubleValue();
Double max = ((BaseIntegerProperty) property).getMaximum() == null ? null : ((BaseIntegerProperty) property).getMaximum().doubleValue();
return (long) randomNumber(min, max);
} else if (property instanceof BaseIntegerProperty) { // Includes IntegerProperty
Double min = ((BaseIntegerProperty) property).getMinimum() == null ? null : ((BaseIntegerProperty) property).getMinimum().doubleValue();
Double max = ((BaseIntegerProperty) property).getMaximum() == null ? null : ((BaseIntegerProperty) property).getMaximum().doubleValue();
return (int) randomNumber(min, max);
} else if (property instanceof MapProperty) {
Map<String, Object> mp = new HashMap<String, Object>();
if (property.getName() != null) {
Expand All @@ -126,27 +171,48 @@ protected Object resolvePropertyToExample(String mediaType, Property property, S
return "{}";
} else if (property instanceof RefProperty) {
String simpleName = ((RefProperty) property).getSimpleRef();
logger.debug("Ref property, simple name: {}", simpleName);
Model model = examples.get(simpleName);
if (model != null) {
return resolveModelToExample(simpleName, mediaType, model, processedModels);
}
logger.warn("Ref property with empty model.");
} else if (property instanceof UUIDProperty) {
return "046b6c7f-0b8a-43b9-b35d-6489e6daee91";
}

return "";
}

public Object resolveModelToExample(String name, String mediaType, Model model, Set<String> processedModels) {
private double randomNumber(Double min, Double max) {
if (min != null && max != null) {
double range = max - min;
return Math.random() * range + min;
} else if (min != null) {
return Math.random() + min;
} else if (max != null) {
return Math.random() * max;
} else {
return Math.random() * 10;
}
}

private Object resolveModelToExample(String name, String mediaType, Model model, Set<String> processedModels) {
if (processedModels.contains(name)) {
return "";
}
if (model instanceof ModelImpl) {
processedModels.add(name);
ModelImpl impl = (ModelImpl) model;
Map<String, Object> values = new HashMap<String, Object>();
Map<String, Object> values = new HashMap<>();

logger.debug("Resolving model '{}' to example", name);

if (impl.getProperties() != null) {
if (impl.getExample() != null) {
logger.debug("Using example from spec: {}", impl.getExample());
return impl.getExample();
} else if (impl.getProperties() != null) {
logger.debug("Creating example from model values");
for (String propertyName : impl.getProperties().keySet()) {
Property property = impl.getProperties().get(propertyName);
values.put(propertyName, resolvePropertyToExample(mediaType, property, processedModels));
Expand Down
8 changes: 4 additions & 4 deletions samples/server/petstore/nodejs/api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -586,17 +586,17 @@ paths:
description: "User not found"
x-swagger-router-controller: "User"
securityDefinitions:
api_key:
type: "apiKey"
name: "api_key"
in: "header"
petstore_auth:
type: "oauth2"
authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog"
flow: "implicit"
scopes:
write:pets: "modify pets in your account"
read:pets: "read your pets"
api_key:
type: "apiKey"
name: "api_key"
in: "header"
definitions:
Order:
type: "object"
Expand Down
66 changes: 33 additions & 33 deletions samples/server/petstore/nodejs/controllers/PetService.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ exports.findPetsByStatus = function(args, res, next) {
**/
var examples = {};
examples['application/json'] = [ {
"tags" : [ {
"id" : 123456789,
"name" : "aeiou"
} ],
"id" : 123456789,
"photoUrls" : [ "aeiou" ],
"name" : "doggie",
"id" : 1,
"category" : {
"id" : 123456789,
"name" : "aeiou"
"name" : "aeiou",
"id" : 7
},
"status" : "aeiou",
"name" : "doggie",
"photoUrls" : [ "aeiou" ]
"tags" : [ {
"name" : "aeiou",
"id" : 2
} ],
"status" : "available"
} ];
if (Object.keys(examples).length > 0) {
res.setHeader('Content-Type', 'application/json');
Expand All @@ -64,18 +64,18 @@ exports.findPetsByTags = function(args, res, next) {
**/
var examples = {};
examples['application/json'] = [ {
"tags" : [ {
"id" : 123456789,
"name" : "aeiou"
} ],
"id" : 123456789,
"photoUrls" : [ "aeiou" ],
"name" : "doggie",
"id" : 9,
"category" : {
"id" : 123456789,
"name" : "aeiou"
"name" : "aeiou",
"id" : 7
},
"status" : "aeiou",
"name" : "doggie",
"photoUrls" : [ "aeiou" ]
"tags" : [ {
"name" : "aeiou",
"id" : 4
} ],
"status" : "available"
} ];
if (Object.keys(examples).length > 0) {
res.setHeader('Content-Type', 'application/json');
Expand All @@ -95,18 +95,18 @@ exports.getPetById = function(args, res, next) {
**/
var examples = {};
examples['application/json'] = {
"tags" : [ {
"id" : 123456789,
"name" : "aeiou"
} ],
"id" : 123456789,
"photoUrls" : [ "aeiou" ],
"name" : "doggie",
"id" : 4,
"category" : {
"id" : 123456789,
"name" : "aeiou"
"name" : "aeiou",
"id" : 4
},
"status" : "aeiou",
"name" : "doggie",
"photoUrls" : [ "aeiou" ]
"tags" : [ {
"name" : "aeiou",
"id" : 4
} ],
"status" : "available"
};
if (Object.keys(examples).length > 0) {
res.setHeader('Content-Type', 'application/json');
Expand Down Expand Up @@ -152,9 +152,9 @@ exports.uploadFile = function(args, res, next) {
**/
var examples = {};
examples['application/json'] = {
"message" : "aeiou",
"code" : 123,
"type" : "aeiou"
"code" : 7,
"type" : "aeiou",
"message" : "aeiou"
};
if (Object.keys(examples).length > 0) {
res.setHeader('Content-Type', 'application/json');
Expand Down
Loading