diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java index 54455f49c897..6d4264f48c1e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java @@ -787,8 +787,8 @@ public List generate() { configureOpenAPIInfo(); // resolve inline models - //InlineModelResolver inlineModelResolver = new InlineModelResolver(); - //inlineModelResolver.flatten(openAPI); + InlineModelResolver inlineModelResolver = new InlineModelResolver(); + inlineModelResolver.flatten(openAPI); List files = new ArrayList(); // models diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java new file mode 100644 index 000000000000..057939f680b4 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/InlineModelResolver.java @@ -0,0 +1,533 @@ +package org.openapitools.codegen; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.*; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.RequestBody; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.core.util.Json; +import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import java.util.ArrayList; +import io.swagger.v3.oas.models.media.XML; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class InlineModelResolver { + private OpenAPI openapi; + private boolean skipMatches; + static Logger LOGGER = LoggerFactory.getLogger(InlineModelResolver.class); + Map addedModels = new HashMap(); + Map generatedSignature = new HashMap(); + + public void flatten(OpenAPI openapi) { + this.openapi = openapi; + + if (openapi.getComponents() == null) { + return; // There's nothing here + } + + if (openapi.getComponents().getSchemas() == null) { + openapi.getComponents().setSchemas(new HashMap()); + } + // operations + Map paths = openapi.getPaths(); + Map models = openapi.getComponents().getSchemas(); + if (paths != null) { + for (String pathname : paths.keySet()) { + PathItem path = paths.get(pathname); + for (Operation operation : path.readOperations()) { + RequestBody requestBody = operation.getRequestBody(); + if (requestBody != null) { + Schema model = ModelUtils.getSchemaFromRequestBody(requestBody); + if (model instanceof ObjectSchema) { + Schema obj = (Schema) model; + if (obj.getType() == null || "object".equals(obj.getType())) { + if (obj.getProperties() != null && obj.getProperties().size() > 0) { + flattenProperties(obj.getProperties(), pathname); + // for model name, use "title" if defined, otherwise default to 'inline_object' + String modelName = resolveModelName(obj.getTitle(), "inline_object"); + addGenerated(modelName, model); + openapi.getComponents().addSchemas(modelName, model); + + // create request body + RequestBody rb = new RequestBody(); + Content content = new Content(); + MediaType mt = new MediaType(); + Schema schema = new Schema(); + schema.set$ref(modelName); + mt.setSchema(schema); + // TODO assume JSON, need to support other payload later + content.addMediaType("application/json", mt); + rb.setContent(content); + // add to openapi "components" + if (openapi.getComponents().getRequestBodies() == null) { + Map requestBodies = new HashMap(); + requestBodies.put(modelName, rb); + openapi.getComponents().setRequestBodies(requestBodies); + } else { + openapi.getComponents().getRequestBodies().put(modelName, rb); + } + + // update requestBody to use $ref instead of inline def + requestBody.set$ref(modelName); + + } + } + } else if (model instanceof ArraySchema) { + ArraySchema am = (ArraySchema) model; + Schema inner = am.getItems(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), pathname); + String modelName = resolveModelName(op.getTitle(), null); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + am.setItems(schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + am.setItems(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } + } + + List parameters = operation.getParameters(); + if (parameters != null) { + for (Parameter parameter : parameters) { + if (parameter.getSchema() != null) { + Schema model = parameter.getSchema(); + if (model instanceof ObjectSchema) { + Schema obj = (Schema) model; + if (obj.getType() == null || "object".equals(obj.getType())) { + if (obj.getProperties() != null && obj.getProperties().size() > 0) { + flattenProperties(obj.getProperties(), pathname); + String modelName = resolveModelName(obj.getTitle(), parameter.getName()); + + parameter.$ref(modelName); + addGenerated(modelName, model); + openapi.getComponents().addSchemas(modelName, model); + } + } + } else if (model instanceof ArraySchema) { + ArraySchema am = (ArraySchema) model; + Schema inner = am.getItems(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), pathname); + String modelName = resolveModelName(op.getTitle(), parameter.getName()); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + am.setItems(schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + am.setItems(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } + } + } + } + Map responses = operation.getResponses(); + if (responses != null) { + for (String key : responses.keySet()) { + ApiResponse response = responses.get(key); + if (ModelUtils.getSchemaFromResponse(response) != null) { + Schema property = ModelUtils.getSchemaFromResponse(response); + if (property instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) property; + if (op.getProperties() != null && op.getProperties().size() > 0) { + String modelName = resolveModelName(op.getTitle(), "inline_response_" + key); + Schema model = modelFromProperty(op, modelName); + String existing = matchGenerated(model); + Content content = response.getContent(); + for (MediaType mediaType : content.values()) { + if (existing != null) { + Schema schema = this.makeSchema(existing, property); + schema.setRequired(op.getRequired()); + mediaType.setSchema(schema); + } else { + Schema schema = this.makeSchema(modelName, property); + schema.setRequired(op.getRequired()); + mediaType.setSchema(schema); + addGenerated(modelName, model); + openapi.getComponents().addSchemas(modelName, model); + } + } + } + } else if (property instanceof ArraySchema) { + ArraySchema ap = (ArraySchema) property; + Schema inner = ap.getItems(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), pathname); + String modelName = resolveModelName(op.getTitle(), + "inline_response_" + key); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = this.makeSchema(existing, op); + schema.setRequired(op.getRequired()); + ap.setItems(schema); + } else { + Schema schema = this.makeSchema(modelName, op); + schema.setRequired(op.getRequired()); + ap.setItems(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } else if (property instanceof MapSchema) { + MapSchema mp = (MapSchema) property; + Schema innerProperty = (Schema) mp.getAdditionalProperties(); + if (innerProperty instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) innerProperty; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), pathname); + String modelName = resolveModelName(op.getTitle(), + "inline_response_" + key); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + mp.setAdditionalProperties(schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + mp.setAdditionalProperties(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } + } + } + } + } + } + } + // definitions + if (models != null) { + List modelNames = new ArrayList(models.keySet()); + for (String modelName : modelNames) { + Schema model = models.get(modelName); + if (model instanceof Schema) { + Schema m = (Schema) model; + Map properties = m.getProperties(); + flattenProperties(properties, modelName); + fixStringModel(m); + } else if (ModelUtils.isArraySchema(model)) { + ArraySchema m = (ArraySchema) model; + Schema inner = m.getItems(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + String innerModelName = resolveModelName(op.getTitle(), modelName + "_inner"); + Schema innerModel = modelFromProperty(op, innerModelName); + String existing = matchGenerated(innerModel); + if (existing == null) { + openapi.getComponents().addSchemas(innerModelName, innerModel); + addGenerated(innerModelName, innerModel); + Schema schema = new Schema().$ref(innerModelName); + schema.setRequired(op.getRequired()); + m.setItems(schema); + } else { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + m.setItems(schema); + } + } + } + } else if (ModelUtils.isComposedSchema(model)) { + ComposedSchema m = (ComposedSchema) model; + if (m.getAllOf() != null && !m.getAllOf().isEmpty()) { + Schema child = null; + for (Schema component : m.getAllOf()) { + if (component.get$ref() == null) { + child = component; + } + } + if (child != null) { + Map properties = child.getProperties(); + flattenProperties(properties, modelName); + } + } + } + } + } + } + + /** + * This function fix models that are string (mostly enum). Before this fix, the + * example would look something like that in the doc: "\"example from def\"" + * + * @param m Schema implementation + */ + private void fixStringModel(Schema m) { + if (m.getType() != null && m.getType().equals("string") && m.getExample() != null) { + String example = m.getExample().toString(); + if (example.substring(0, 1).equals("\"") && example.substring(example.length() - 1).equals("\"")) { + m.setExample(example.substring(1, example.length() - 1)); + } + } + } + + private String resolveModelName(String title, String key) { + if (title == null) { + return uniqueName(key); + } else { + return uniqueName(title); + } + } + + public String matchGenerated(Schema model) { + if (this.skipMatches) { + return null; + } + String json = Json.pretty(model); + if (generatedSignature.containsKey(json)) { + return generatedSignature.get(json); + } + return null; + } + + public void addGenerated(String name, Schema model) { + generatedSignature.put(Json.pretty(model), name); + } + + public String uniqueName(String key) { + if (key == null) { + key = "NULL_UNIQUE_NAME"; + LOGGER.warn("null key found. Default to NULL_UNIQUE_NAME"); + } + int count = 0; + boolean done = false; + key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter + // should not be + // assigned. Also declare + // the methods parameters + // as 'final'. + while (!done) { + String name = key; + if (count > 0) { + name = key + "_" + count; + } + if (openapi.getComponents().getSchemas() == null) { + return name; + } else if (!openapi.getComponents().getSchemas().containsKey(name)) { + return name; + } + count += 1; + } + return key; + } + + public void flattenProperties(Map properties, String path) { + if (properties == null) { + return; + } + Map propsToUpdate = new HashMap(); + Map modelsToAdd = new HashMap(); + for (String key : properties.keySet()) { + Schema property = properties.get(key); + if (property instanceof ObjectSchema && ((ObjectSchema) property).getProperties() != null + && ((ObjectSchema) property).getProperties().size() > 0) { + ObjectSchema op = (ObjectSchema) property; + String modelName = resolveModelName(op.getTitle(), path + "_" + key); + Schema model = modelFromProperty(op, modelName); + String existing = matchGenerated(model); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + propsToUpdate.put(key, schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + propsToUpdate.put(key, schema); + modelsToAdd.put(modelName, model); + addGenerated(modelName, model); + openapi.getComponents().addSchemas(modelName, model); + } + } else if (property instanceof ArraySchema) { + ArraySchema ap = (ArraySchema) property; + Schema inner = ap.getItems(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), path); + String modelName = resolveModelName(op.getTitle(), path + "_" + key); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + ap.setItems(schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + ap.setItems(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } + if (ModelUtils.isMapSchema(property)) { + Schema inner = (Schema) property.getAdditionalProperties(); + if (inner instanceof ObjectSchema) { + ObjectSchema op = (ObjectSchema) inner; + if (op.getProperties() != null && op.getProperties().size() > 0) { + flattenProperties(op.getProperties(), path); + String modelName = resolveModelName(op.getTitle(), path + "_" + key); + Schema innerModel = modelFromProperty(op, modelName); + String existing = matchGenerated(innerModel); + if (existing != null) { + Schema schema = new Schema().$ref(existing); + schema.setRequired(op.getRequired()); + property.setAdditionalProperties(schema); + } else { + Schema schema = new Schema().$ref(modelName); + schema.setRequired(op.getRequired()); + property.setAdditionalProperties(schema); + addGenerated(modelName, innerModel); + openapi.getComponents().addSchemas(modelName, innerModel); + } + } + } + } + } + if (propsToUpdate.size() > 0) { + for (String key : propsToUpdate.keySet()) { + properties.put(key, propsToUpdate.get(key)); + } + } + for (String key : modelsToAdd.keySet()) { + openapi.getComponents().addSchemas(key, modelsToAdd.get(key)); + this.addedModels.put(key, modelsToAdd.get(key)); + } + } + + @SuppressWarnings("static-method") + public Schema modelFromProperty(ArraySchema object, @SuppressWarnings("unused") String path) { + String description = object.getDescription(); + String example = null; + Object obj = object.getExample(); + + if (obj != null) { + example = obj.toString(); + } + Schema inner = object.getItems(); + if (inner instanceof ObjectSchema) { + ArraySchema model = new ArraySchema(); + model.setDescription(description); + model.setExample(example); + model.setItems(object.getItems()); + model.setName(object.getName()); + return model; + } + return null; + } + + public Schema modelFromProperty(ObjectSchema object, String path) { + String description = object.getDescription(); + String example = null; + Object obj = object.getExample(); + if (obj != null) { + example = obj.toString(); + } + XML xml = object.getXml(); + Map properties = object.getProperties(); + Schema model = new Schema(); + model.setDescription(description); + model.setExample(example); + model.setName(object.getName()); + model.setXml(xml); + if (properties != null) { + flattenProperties(properties, path); + model.setProperties(properties); + } + return model; + } + + @SuppressWarnings("static-method") + public Schema modelFromProperty(MapSchema object, @SuppressWarnings("unused") String path) { + String description = object.getDescription(); + String example = null; + Object obj = object.getExample(); + if (obj != null) { + example = obj.toString(); + } + ArraySchema model = new ArraySchema(); + model.setDescription(description); + model.setName(object.getName()); + model.setExample(example); + model.setItems((Schema) object.getAdditionalProperties()); + return model; + } + + /** + * Make a Schema + * + * @param ref new property name + * @param property Schema + * @return {@link Schema} A constructed OpenAPI property + */ + public Schema makeSchema(String ref, Schema property) { + Schema newProperty = new Schema().$ref(ref); + this.copyVendorExtensions(property, newProperty); + return newProperty; + } + + /** + * Copy vendor extensions from Model to another Model + * + * @param source source property + * @param target target property + */ + + public void copyVendorExtensions(Schema source, Schema target) { + Map vendorExtensions = source.getExtensions(); + for (String extName : vendorExtensions.keySet()) { + target.addExtension(extName, vendorExtensions.get(extName)); + } + } + + public boolean isSkipMatches() { + return skipMatches; + } + + public void setSkipMatches(boolean skipMatches) { + this.skipMatches = skipMatches; + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java new file mode 100644 index 000000000000..8ec2ee8ef1dd --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/InlineModelResolverTest.java @@ -0,0 +1,1012 @@ +package org.openapitools.codegen; + +import io.swagger.v3.oas.models.*; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.core.util.Json; +import org.apache.commons.lang3.StringUtils; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.testng.AssertJUnit.*; +/* +@SuppressWarnings("static-method") +public class InlineModelResolverTest { + @Test + public void resolveInlineModelTestWithoutTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("address", new ObjectProperty() + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + ModelImpl user = (ModelImpl)openapi.getDefinitions().get("User"); + + assertNotNull(user); + assertTrue(user.getProperties().get("address") instanceof RefProperty); + + ModelImpl address = (ModelImpl)openapi.getDefinitions().get("User_address"); + assertNotNull(address); + assertNotNull(address.getProperties().get("city")); + assertNotNull(address.getProperties().get("street")); + } + + @Test + public void resolveInlineModelTestWithTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("address", new ObjectProperty() + .title("UserAddressTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + ModelImpl user = (ModelImpl)openapi.getDefinitions().get("User"); + + assertNotNull(user); + assertTrue(user.getProperties().get("address") instanceof RefProperty); + + ModelImpl address = (ModelImpl)openapi.getDefinitions().get("UserAddressTitle"); + assertNotNull(address); + assertNotNull(address.getProperties().get("city")); + assertNotNull(address.getProperties().get("street")); + } + + @Test + public void resolveInlineModel2EqualInnerModels() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("address", new ObjectProperty() + .title("UserAddressTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + openapi.addDefinition("AnotherUser", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("lastName", new StringProperty()) + .property("address", new ObjectProperty() + .title("UserAddressTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + ModelImpl user = (ModelImpl)openapi.getDefinitions().get("User"); + + assertNotNull(user); + assertTrue(user.getProperties().get("address") instanceof RefProperty); + + ModelImpl address = (ModelImpl)openapi.getDefinitions().get("UserAddressTitle"); + assertNotNull(address); + assertNotNull(address.getProperties().get("city")); + assertNotNull(address.getProperties().get("street")); + ModelImpl duplicateAddress = (ModelImpl)openapi.getDefinitions().get("UserAddressTitle_0"); + assertNull(duplicateAddress); + } + + @Test + public void resolveInlineModel2DifferentInnerModelsWIthSameTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("address", new ObjectProperty() + .title("UserAddressTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + openapi.addDefinition("AnotherUser", new ModelImpl() + .name("AnotherUser") + .description("a common user") + .property("name", new StringProperty()) + .property("lastName", new StringProperty()) + .property("address", new ObjectProperty() + .title("UserAddressTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()) + .property("apartment", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + ModelImpl user = (ModelImpl)openapi.getDefinitions().get("User"); + + assertNotNull(user); + assertTrue(user.getProperties().get("address") instanceof RefProperty); + + ModelImpl address = (ModelImpl)openapi.getDefinitions().get("UserAddressTitle"); + assertNotNull(address); + assertNotNull(address.getProperties().get("city")); + assertNotNull(address.getProperties().get("street")); + ModelImpl duplicateAddress = (ModelImpl)openapi.getDefinitions().get("UserAddressTitle_1"); + assertNotNull(duplicateAddress); + assertNotNull(duplicateAddress.getProperties().get("city")); + assertNotNull(duplicateAddress.getProperties().get("street")); + assertNotNull(duplicateAddress.getProperties().get("apartment")); + } + + + @Test + public void testInlineResponseModel() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/foo/bar", new Path() + .get(new Operation() + .response(200, new Response() + .description("it works!") + .schema(new ObjectProperty() + .property("name", new StringProperty()).vendorExtension("x-ext", "ext-prop"))))) + .path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(new ObjectProperty() + .property("name", new StringProperty()).vendorExtension("x-ext", "ext-prop"))))); + new InlineModelResolver().flatten(openapi); + + Map responses = openapi.getPaths().get("/foo/bar").getGet().getResponses(); + + Response response = responses.get("200"); + assertNotNull(response); + Property schema = response.getSchema(); + assertTrue(schema instanceof RefProperty); + assertEquals(1, schema.getVendorExtensions().size()); + assertEquals("ext-prop", schema.getVendorExtensions().get("x-ext")); + + ModelImpl model = (ModelImpl)openapi.getDefinitions().get("inline_response_200"); + assertTrue(model.getProperties().size() == 1); + assertNotNull(model.getProperties().get("name")); + assertTrue(model.getProperties().get("name") instanceof StringProperty); + } + + + @Test + public void testInlineResponseModelWithTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + String responseTitle = "GetBarResponse"; + openapi.path("/foo/bar", new Path() + .get(new Operation() + .response(200, new Response() + .description("it works!") + .schema(new ObjectProperty().title(responseTitle) + .property("name", new StringProperty()))))) + .path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(new ObjectProperty() + .property("name", new StringProperty()))))); + new InlineModelResolver().flatten(openapi); + + Map responses = openapi.getPaths().get("/foo/bar").getGet().getResponses(); + + Response response = responses.get("200"); + assertNotNull(response); + assertTrue(response.getSchema() instanceof RefProperty); + + ModelImpl model = (ModelImpl)openapi.getDefinitions().get(responseTitle); + assertTrue(model.getProperties().size() == 1); + assertNotNull(model.getProperties().get("name")); + assertTrue(model.getProperties().get("name") instanceof StringProperty); + } + + + @Test + public void resolveInlineArrayModelWithTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ArrayModel() + .items(new ObjectProperty() + .title("InnerUserTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + Model model = openapi.getDefinitions().get("User"); + assertTrue(model instanceof ArrayModel); + + Model user = openapi.getDefinitions().get("InnerUserTitle"); + assertNotNull(user); + assertEquals("description", user.getDescription()); + } + + @Test + public void resolveInlineArrayModelWithoutTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ArrayModel() + .items(new ObjectProperty() + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("street", new StringProperty()) + .property("city", new StringProperty()))); + + new InlineModelResolver().flatten(openapi); + + Model model = openapi.getDefinitions().get("User"); + assertTrue(model instanceof ArrayModel); + + Model user = openapi.getDefinitions().get("User_inner"); + assertNotNull(user); + assertEquals("description", user.getDescription()); + } + + + + + @Test + public void resolveInlineBodyParameter() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ModelImpl() + .property("address", new ObjectProperty() + .property("street", new StringProperty())) + .property("name", new StringProperty()))))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof RefModel); + + Model body = openapi.getDefinitions().get("body"); + assertTrue(body instanceof ModelImpl); + + ModelImpl impl = (ModelImpl) body; + assertNotNull(impl.getProperties().get("address")); + } + + @Test + public void resolveInlineBodyParameterWithRequired() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ModelImpl() + .property("address", new ObjectProperty() + .property("street", new StringProperty() + .required(true)) + .required(true)) + .property("name", new StringProperty()))))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof RefModel); + + Model body = openapi.getDefinitions().get("body"); + assertTrue(body instanceof ModelImpl); + + ModelImpl impl = (ModelImpl) body; + assertNotNull(impl.getProperties().get("address")); + + Property addressProperty = impl.getProperties().get("address"); + assertTrue(addressProperty instanceof RefProperty); + assertTrue(addressProperty.getRequired()); + + Model helloAddress = openapi.getDefinitions().get("hello_address"); + assertTrue(helloAddress instanceof ModelImpl); + + ModelImpl addressImpl = (ModelImpl) helloAddress; + assertNotNull(addressImpl); + + Property streetProperty = addressImpl.getProperties().get("street"); + assertTrue(streetProperty instanceof StringProperty); + assertTrue(streetProperty.getRequired()); + } + + @Test + public void resolveInlineBodyParameterWithTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + ModelImpl addressModelItem = new ModelImpl(); + String addressModelName = "DetailedAddress"; + addressModelItem.setTitle(addressModelName); + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(addressModelItem + .property("address", new ObjectProperty() + .property("street", new StringProperty())) + .property("name", new StringProperty()))))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof RefModel); + + Model body = openapi.getDefinitions().get(addressModelName); + assertTrue(body instanceof ModelImpl); + + ModelImpl impl = (ModelImpl) body; + assertNotNull(impl.getProperties().get("address")); + } + + @Test + public void notResolveNonModelBodyParameter() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ModelImpl() + .type("string") + .format("binary"))))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof ModelImpl); + ModelImpl m = (ModelImpl) bp.getSchema(); + assertEquals("string", m.getType()); + assertEquals("binary", m.getFormat()); + } + + @Test + public void resolveInlineArrayBodyParameter() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ArrayModel() + .items(new ObjectProperty() + .property("address", new ObjectProperty() + .property("street", new StringProperty()))))))); + + new InlineModelResolver().flatten(openapi); + + Parameter param = openapi.getPaths().get("/hello").getGet().getParameters().get(0); + assertTrue(param instanceof BodyParameter); + + BodyParameter bp = (BodyParameter) param; + Model schema = bp.getSchema(); + + assertTrue(schema instanceof ArrayModel); + + ArrayModel am = (ArrayModel) schema; + Property inner = am.getItems(); + assertTrue(inner instanceof RefProperty); + + RefProperty rp = (RefProperty) inner; + + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/body"); + assertEquals(rp.getSimpleRef(), "body"); + + Model inline = openapi.getDefinitions().get("body"); + assertNotNull(inline); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + RefProperty rpAddress = (RefProperty) impl.getProperties().get("address"); + assertNotNull(rpAddress); + assertEquals(rpAddress.getType(), "ref"); + assertEquals(rpAddress.get$ref(), "#/definitions/hello_address"); + assertEquals(rpAddress.getSimpleRef(), "hello_address"); + + Model inlineProp = openapi.getDefinitions().get("hello_address"); + assertNotNull(inlineProp); + assertTrue(inlineProp instanceof ModelImpl); + ModelImpl implProp = (ModelImpl) inlineProp; + assertNotNull(implProp.getProperties().get("street")); + assertTrue(implProp.getProperties().get("street") instanceof StringProperty); + } + + @Test + public void resolveInlineArrayResponse() throws Exception { + OpenAPI openapi = new OpenAPI(); + + ArrayProperty schema = new ArrayProperty() + .items(new ObjectProperty() + .property("name", new StringProperty()) + .vendorExtension("x-ext", "ext-items")) + .vendorExtension("x-ext", "ext-prop"); + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(schema)))); + + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + assertNotNull(response); + + assertNotNull(response.getSchema()); + Property responseProperty = response.getSchema(); + + // no need to flatten more + assertTrue(responseProperty instanceof ArrayProperty); + + ArrayProperty ap = (ArrayProperty) responseProperty; + assertEquals(1, ap.getVendorExtensions().size()); + assertEquals("ext-prop", ap.getVendorExtensions().get("x-ext")); + + Property p = ap.getItems(); + + assertNotNull(p); + + RefProperty rp = (RefProperty) p; + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/inline_response_200"); + assertEquals(rp.getSimpleRef(), "inline_response_200"); + assertEquals(1, rp.getVendorExtensions().size()); + assertEquals("ext-items", rp.getVendorExtensions().get("x-ext")); + + Model inline = openapi.getDefinitions().get("inline_response_200"); + assertNotNull(inline); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + assertNotNull(impl.getProperties().get("name")); + assertTrue(impl.getProperties().get("name") instanceof StringProperty); + } + + @Test + public void resolveInlineArrayResponseWithTitle() throws Exception { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(new ArrayProperty() + .items(new ObjectProperty() + .title("FooBar") + .property("name", new StringProperty())))))); + + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + assertNotNull(response); + + assertNotNull(response.getSchema()); + Property responseProperty = response.getSchema(); + + // no need to flatten more + assertTrue(responseProperty instanceof ArrayProperty); + + ArrayProperty ap = (ArrayProperty) responseProperty; + Property p = ap.getItems(); + + assertNotNull(p); + + RefProperty rp = (RefProperty) p; + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/"+ "FooBar"); + assertEquals(rp.getSimpleRef(), "FooBar"); + + Model inline = openapi.getDefinitions().get("FooBar"); + assertNotNull(inline); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + assertNotNull(impl.getProperties().get("name")); + assertTrue(impl.getProperties().get("name") instanceof StringProperty); + } + + @Test + public void testInlineMapResponse() throws Exception { + OpenAPI openapi = new OpenAPI(); + + MapProperty schema = new MapProperty(); + schema.setAdditionalProperties(new StringProperty()); + schema.setVendorExtension("x-ext", "ext-prop"); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(schema)))); + new InlineModelResolver().flatten(openapi); + Json.prettyPrint(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + + Property property = response.getSchema(); + assertTrue(property instanceof MapProperty); + assertTrue(openapi.getDefinitions().size() == 0); + assertEquals(1, property.getVendorExtensions().size()); + assertEquals("ext-prop", property.getVendorExtensions().get("x-ext")); + } + + @Test + public void testInlineMapResponseWithObjectProperty() throws Exception { + OpenAPI openapi = new OpenAPI(); + + MapProperty schema = new MapProperty(); + schema.setAdditionalProperties(new ObjectProperty() + .property("name", new StringProperty())); + schema.setVendorExtension("x-ext", "ext-prop"); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(schema)))); + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + Property property = response.getSchema(); + assertTrue(property instanceof MapProperty); + assertEquals(1, property.getVendorExtensions().size()); + assertEquals("ext-prop", property.getVendorExtensions().get("x-ext")); + assertTrue(openapi.getDefinitions().size() == 1); + + Model inline = openapi.getDefinitions().get("inline_response_200"); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + assertNotNull(impl.getProperties().get("name")); + assertTrue(impl.getProperties().get("name") instanceof StringProperty); + } + + @Test + public void testArrayResponse() { + OpenAPI openapi = new OpenAPI(); + + ArrayProperty schema = new ArrayProperty(); + schema.setItems(new ObjectProperty() + .property("name", new StringProperty())); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(schema)))); + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + assertTrue(response.getSchema() instanceof ArrayProperty); + + ArrayProperty am = (ArrayProperty) response.getSchema(); + Property items = am.getItems(); + assertTrue(items instanceof RefProperty); + RefProperty rp = (RefProperty) items; + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/inline_response_200"); + assertEquals(rp.getSimpleRef(), "inline_response_200"); + + Model inline = openapi.getDefinitions().get("inline_response_200"); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + assertNotNull(impl.getProperties().get("name")); + assertTrue(impl.getProperties().get("name") instanceof StringProperty); + } + + @Test + public void testBasicInput() { + OpenAPI openapi = new OpenAPI(); + + ModelImpl user = new ModelImpl() + .property("name", new StringProperty()); + + openapi.path("/foo/baz", new Path() + .post(new Operation() + .parameter(new BodyParameter() + .name("myBody") + .schema(new RefModel("User"))))); + + openapi.addDefinition("User", user); + + new InlineModelResolver().flatten(openapi); + + Json.prettyPrint(openapi); + } + + @Test + public void testArbitraryObjectBodyParam() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ModelImpl())))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof ModelImpl); + ModelImpl m = (ModelImpl) bp.getSchema(); + assertNull(m.getType()); + } + + @Test + public void testArbitraryObjectBodyParamInline() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ModelImpl() + .property("arbitrary", new ObjectProperty()))))); + + new InlineModelResolver().flatten(openapi); + + Operation operation = openapi.getPaths().get("/hello").getGet(); + BodyParameter bp = (BodyParameter)operation.getParameters().get(0); + assertTrue(bp.getSchema() instanceof RefModel); + + Model body = openapi.getDefinitions().get("body"); + assertTrue(body instanceof ModelImpl); + + ModelImpl impl = (ModelImpl) body; + Property p = impl.getProperties().get("arbitrary"); + assertNotNull(p); + assertTrue(p instanceof ObjectProperty); + } + + @Test + public void testArbitraryObjectBodyParamWithArray() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ArrayModel() + .items(new ObjectProperty()))))); + + new InlineModelResolver().flatten(openapi); + + Parameter param = openapi.getPaths().get("/hello").getGet().getParameters().get(0); + assertTrue(param instanceof BodyParameter); + + BodyParameter bp = (BodyParameter) param; + Model schema = bp.getSchema(); + + assertTrue(schema instanceof ArrayModel); + + ArrayModel am = (ArrayModel) schema; + Property inner = am.getItems(); + assertTrue(inner instanceof ObjectProperty); + + ObjectProperty op = (ObjectProperty) inner; + assertNotNull(op); + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectBodyParamArrayInline() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/hello", new Path() + .get(new Operation() + .parameter(new BodyParameter() + .name("body") + .schema(new ArrayModel() + .items(new ObjectProperty() + .property("arbitrary", new ObjectProperty())))))); + + new InlineModelResolver().flatten(openapi); + + Parameter param = openapi.getPaths().get("/hello").getGet().getParameters().get(0); + assertTrue(param instanceof BodyParameter); + + BodyParameter bp = (BodyParameter) param; + Model schema = bp.getSchema(); + + assertTrue(schema instanceof ArrayModel); + + ArrayModel am = (ArrayModel) schema; + Property inner = am.getItems(); + assertTrue(inner instanceof RefProperty); + + RefProperty rp = (RefProperty) inner; + + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/body"); + assertEquals(rp.getSimpleRef(), "body"); + + Model inline = openapi.getDefinitions().get("body"); + assertNotNull(inline); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + Property p = impl.getProperties().get("arbitrary"); + assertNotNull(p); + assertTrue(p instanceof ObjectProperty); + } + + @Test + public void testArbitraryObjectResponse() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/foo/bar", new Path() + .get(new Operation() + .response(200, new Response() + .description("it works!") + .schema(new ObjectProperty())))); + new InlineModelResolver().flatten(openapi); + + Map responses = openapi.getPaths().get("/foo/bar").getGet().getResponses(); + + Response response = responses.get("200"); + assertNotNull(response); + assertTrue(response.getSchema() instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) response.getSchema(); + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectResponseArray() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .description("it works!") + .schema(new ArrayProperty() + .items(new ObjectProperty()))))); + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + assertTrue(response.getSchema() instanceof ArrayProperty); + + ArrayProperty am = (ArrayProperty) response.getSchema(); + Property items = am.getItems(); + assertTrue(items instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) items; + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectResponseArrayInline() { + OpenAPI openapi = new OpenAPI(); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .vendorExtension("x-foo", "bar") + .description("it works!") + .schema(new ArrayProperty() + .items(new ObjectProperty() + .property("arbitrary", new ObjectProperty())))))); + + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + assertNotNull(response); + + assertNotNull(response.getSchema()); + Property responseProperty = response.getSchema(); + assertTrue(responseProperty instanceof ArrayProperty); + + ArrayProperty ap = (ArrayProperty) responseProperty; + Property p = ap.getItems(); + assertNotNull(p); + + RefProperty rp = (RefProperty) p; + assertEquals(rp.getType(), "ref"); + assertEquals(rp.get$ref(), "#/definitions/inline_response_200"); + assertEquals(rp.getSimpleRef(), "inline_response_200"); + + Model inline = openapi.getDefinitions().get("inline_response_200"); + assertNotNull(inline); + assertTrue(inline instanceof ModelImpl); + ModelImpl impl = (ModelImpl) inline; + Property inlineProp = impl.getProperties().get("arbitrary"); + assertNotNull(inlineProp); + assertTrue(inlineProp instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) inlineProp; + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectResponseMapInline() { + OpenAPI openapi = new OpenAPI(); + + MapProperty schema = new MapProperty(); + schema.setAdditionalProperties(new ObjectProperty()); + + openapi.path("/foo/baz", new Path() + .get(new Operation() + .response(200, new Response() + .description("it works!") + .schema(schema)))); + new InlineModelResolver().flatten(openapi); + + Response response = openapi.getPaths().get("/foo/baz").getGet().getResponses().get("200"); + + Property property = response.getSchema(); + assertTrue(property instanceof MapProperty); + assertTrue(openapi.getDefinitions().size() == 0); + Property inlineProp = ((MapProperty) property).getAdditionalProperties(); + assertTrue(inlineProp instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) inlineProp; + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectModelInline() { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ModelImpl() + .name("user") + .description("a common user") + .property("name", new StringProperty()) + .property("arbitrary", new ObjectProperty() + .title("title") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name"))); + + new InlineModelResolver().flatten(openapi); + + ModelImpl user = (ModelImpl)openapi.getDefinitions().get("User"); + assertNotNull(user); + Property inlineProp = user.getProperties().get("arbitrary"); + assertTrue(inlineProp instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) inlineProp; + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectModelWithArrayInlineWithoutTitle() { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ArrayModel() + .items(new ObjectProperty() + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("arbitrary", new ObjectProperty()))); + + new InlineModelResolver().flatten(openapi); + + Model model = openapi.getDefinitions().get("User"); + assertTrue(model instanceof ArrayModel); + ArrayModel am = (ArrayModel) model; + Property inner = am.getItems(); + assertTrue(inner instanceof RefProperty); + + ModelImpl userInner = (ModelImpl)openapi.getDefinitions().get("User_inner"); + assertNotNull(userInner); + Property inlineProp = userInner.getProperties().get("arbitrary"); + assertTrue(inlineProp instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) inlineProp; + assertNull(op.getProperties()); + } + + @Test + public void testArbitraryObjectModelWithArrayInlineWithTitle() { + OpenAPI openapi = new OpenAPI(); + + openapi.addDefinition("User", new ArrayModel() + .items(new ObjectProperty() + .title("InnerUserTitle") + ._default("default") + .access("access") + .readOnly(false) + .required(true) + .description("description") + .name("name") + .property("arbitrary", new ObjectProperty()))); + + new InlineModelResolver().flatten(openapi); + + Model model = openapi.getDefinitions().get("User"); + assertTrue(model instanceof ArrayModel); + ArrayModel am = (ArrayModel) model; + Property inner = am.getItems(); + assertTrue(inner instanceof RefProperty); + + ModelImpl userInner = (ModelImpl)openapi.getDefinitions().get("InnerUserTitle"); + assertNotNull(userInner); + Property inlineProp = userInner.getProperties().get("arbitrary"); + assertTrue(inlineProp instanceof ObjectProperty); + ObjectProperty op = (ObjectProperty) inlineProp; + assertNull(op.getProperties()); + } + + @Test + public void testEmptyExampleOnStrinngTypeModels() { + OpenAPI openapi = new OpenAPI(); + + RefProperty refProperty = new RefProperty(); + refProperty.set$ref("#/definitions/Test"); + + openapi.path("/hello", new Path() + .get(new Operation() + .response(200, new Response() + .schema(new ArrayProperty() + .items(refProperty))))); + + openapi.addDefinition("Test", new ModelImpl() + .example(StringUtils.EMPTY) + .type("string")); + new InlineModelResolver().flatten(openapi); + } +} +*/ \ No newline at end of file