Merge remote-tracking branch 'origin/master' into 2.3.0

This commit is contained in:
wing328 2016-10-05 16:07:18 +08:00
commit 71b2d5c942
31 changed files with 378 additions and 62 deletions

3
.gitignore vendored
View File

@ -4,6 +4,7 @@ out/
*.iws *.iws
classpath.txt classpath.txt
version.properties version.properties
!modules/swagger-codegen-cli/src/main/resources/version.properties
.project .project
.classpath .classpath
lib/* lib/*
@ -33,7 +34,7 @@ packages/
/target /target
/generated-files /generated-files
/nbactions.xml nbactions.xml
# scalatra # scalatra
samples/server-generator/scalatra/output samples/server-generator/scalatra/output

View File

@ -782,6 +782,7 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [Mporium](http://mporium.com/) - [Mporium](http://mporium.com/)
- [nViso](http://www.nviso.ch/) - [nViso](http://www.nviso.ch/)
- [Okiok](https://www.okiok.com) - [Okiok](https://www.okiok.com)
- [Onedata](http://onedata.org)
- [OSDN](https://osdn.jp) - [OSDN](https://osdn.jp)
- [PagerDuty](https://www.pagerduty.com) - [PagerDuty](https://www.pagerduty.com)
- [Pepipost](https://www.pepipost.com) - [Pepipost](https://www.pepipost.com)
@ -881,6 +882,7 @@ Here is a list of template creators:
* Erlang Server: @galaxie * Erlang Server: @galaxie
* Go Server: @guohuang * Go Server: @guohuang
* Haskell Servant: @algas * Haskell Servant: @algas
* Java Undertow: @stevehu
* Java Spring Boot: @diyfr * Java Spring Boot: @diyfr
* JAX-RS RestEasy: @chameleon82 * JAX-RS RestEasy: @chameleon82
* JAX-RS CXF: @hiveship * JAX-RS CXF: @hiveship

View File

@ -18,6 +18,7 @@
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes> <excludes>
<exclude>logback.xml</exclude> <exclude>logback.xml</exclude>
</excludes> </excludes>

View File

@ -6,6 +6,7 @@ import io.swagger.codegen.cmd.ConfigHelp;
import io.swagger.codegen.cmd.Generate; import io.swagger.codegen.cmd.Generate;
import io.swagger.codegen.cmd.Langs; import io.swagger.codegen.cmd.Langs;
import io.swagger.codegen.cmd.Meta; import io.swagger.codegen.cmd.Meta;
import io.swagger.codegen.cmd.Version;
/** /**
* User: lanwen * User: lanwen
@ -21,16 +22,20 @@ public class SwaggerCodegen {
public static void main(String[] args) { public static void main(String[] args) {
String version = Version.readVersionFromResources();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("swagger-codegen-cli") Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("swagger-codegen-cli")
.withDescription("Swagger code generator CLI. More info on swagger.io") .withDescription(String.format(
"Swagger code generator CLI (version %s). More info on swagger.io",
version))
.withDefaultCommand(Langs.class) .withDefaultCommand(Langs.class)
.withCommands( .withCommands(
Generate.class, Generate.class,
Meta.class, Meta.class,
Langs.class, Langs.class,
Help.class, Help.class,
ConfigHelp.class ConfigHelp.class,
Version.class
); );
builder.build().parse(args).run(); builder.build().parse(args).run();

View File

@ -68,12 +68,8 @@ public class Meta implements Runnable {
"src/main/resources/META-INF/services", "io.swagger.codegen.CodegenConfig") "src/main/resources/META-INF/services", "io.swagger.codegen.CodegenConfig")
); );
String swaggerVersion = this.getClass().getPackage().getImplementationVersion(); String swaggerVersion = Version.readVersionFromResources();
// if the code is running outside of the jar (i.e. from the IDE), it will not have the version available.
// let's default it with something.
if (swaggerVersion==null) {
swaggerVersion = "2.1.3";
}
Map<String, Object> data = new ImmutableMap.Builder<String, Object>() Map<String, Object> data = new ImmutableMap.Builder<String, Object>()
.put("generatorPackage", targetPackage) .put("generatorPackage", targetPackage)
.put("generatorClass", mainClass) .put("generatorClass", mainClass)

View File

@ -0,0 +1,45 @@
package io.swagger.codegen.cmd;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import io.airlift.airline.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Command(name = "version", description = "Show version information")
public class Version implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(Meta.class);
private static final String VERSION_PLACEHOLDER = "${project.version}";
private static final String UNREADABLE_VERSION = "unreadable";
private static final String UNSET_VERSION = "unset";
private static final String UNKNOWN_VERSION = "unknown";
public static String readVersionFromResources() {
Properties versionProperties = new Properties();
try (InputStream is = Version.class.getResourceAsStream("/version.properties")) {
versionProperties.load(is);
} catch (IOException ex) {
LOGGER.error("Error loading version properties", ex);
return UNREADABLE_VERSION;
}
String version = versionProperties.getProperty("version", UNKNOWN_VERSION).trim();
if (VERSION_PLACEHOLDER.equals(version)) {
return UNSET_VERSION;
} else {
return version;
}
}
@Override
public void run() {
String version = readVersionFromResources();
System.out.println(version);
}
}

View File

@ -0,0 +1 @@
version = ${project.version}

View File

@ -100,6 +100,7 @@ public class DefaultCodegen {
protected List<CliOption> cliOptions = new ArrayList<CliOption>(); protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite; protected boolean skipOverwrite;
protected boolean supportsInheritance; protected boolean supportsInheritance;
protected boolean supportsMixins;
protected Map<String, String> supportedLibraries = new LinkedHashMap<String, String>(); protected Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
protected String library; protected String library;
protected Boolean sortParamsByRequiredFlag = true; protected Boolean sortParamsByRequiredFlag = true;
@ -1235,7 +1236,7 @@ public class DefaultCodegen {
List<String> required = new ArrayList<String>(); List<String> required = new ArrayList<String>();
Map<String, Property> allProperties; Map<String, Property> allProperties;
List<String> allRequired; List<String> allRequired;
if (supportsInheritance) { if (supportsInheritance || supportsMixins) {
allProperties = new LinkedHashMap<String, Property>(); allProperties = new LinkedHashMap<String, Property>();
allRequired = new ArrayList<String>(); allRequired = new ArrayList<String>();
m.allVars = new ArrayList<CodegenProperty>(); m.allVars = new ArrayList<CodegenProperty>();
@ -1256,17 +1257,20 @@ public class DefaultCodegen {
interfaceModel = allDefinitions.get(_interface.getSimpleRef()); interfaceModel = allDefinitions.get(_interface.getSimpleRef());
} }
// set first interface with discriminator found as parent // set first interface with discriminator found as parent
if (parent == null && interfaceModel instanceof ModelImpl && ((ModelImpl) interfaceModel).getDiscriminator() != null) { if (parent == null
&& ((interfaceModel instanceof ModelImpl && ((ModelImpl) interfaceModel).getDiscriminator() != null)
|| (interfaceModel instanceof ComposedModel && isDiscriminatorInInterfaceTree((ComposedModel) interfaceModel, allDefinitions)))) {
parent = _interface; parent = _interface;
} else { } else {
final String interfaceRef = toModelName(_interface.getSimpleRef()); final String interfaceRef = toModelName(_interface.getSimpleRef());
m.interfaces.add(interfaceRef); m.interfaces.add(interfaceRef);
addImport(m, interfaceRef); addImport(m, interfaceRef);
if (allDefinitions != null) { if (allDefinitions != null) {
if (!supportsMixins) {
addProperties(properties, required, interfaceModel, allDefinitions);
}
if (supportsInheritance) { if (supportsInheritance) {
addProperties(allProperties, allRequired, interfaceModel, allDefinitions); addProperties(allProperties, allRequired, interfaceModel, allDefinitions);
} else {
addProperties(properties, required, interfaceModel, allDefinitions);
} }
} }
} }
@ -1325,6 +1329,30 @@ public class DefaultCodegen {
return m; return m;
} }
/**
* Recursively look for a discriminator in the interface tree
*/
private boolean isDiscriminatorInInterfaceTree(ComposedModel model, Map<String, Model> allDefinitions) {
if (model == null || allDefinitions == null)
return false;
Model child = ((ComposedModel) model).getChild();
if (child instanceof ModelImpl && ((ModelImpl) child).getDiscriminator() != null) {
return true;
}
for (RefModel _interface : model.getInterfaces()) {
Model interfaceModel = allDefinitions.get(_interface.getSimpleRef());
if (interfaceModel instanceof ModelImpl && ((ModelImpl) interfaceModel).getDiscriminator() != null) {
return true;
}
if (interfaceModel instanceof ComposedModel) {
return isDiscriminatorInInterfaceTree((ComposedModel) interfaceModel, allDefinitions);
}
}
return false;
}
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, ModelImpl swaggerModel) { protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, ModelImpl swaggerModel) {
MapProperty mapProperty = new MapProperty(swaggerModel.getAdditionalProperties()); MapProperty mapProperty = new MapProperty(swaggerModel.getAdditionalProperties());
addParentContainer(codegenModel, codegenModel.name, mapProperty); addParentContainer(codegenModel, codegenModel.name, mapProperty);

View File

@ -145,10 +145,6 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
} }
if(!new java.io.File(controllerPackage + File.separator + defaultController + ".py").exists()) { if(!new java.io.File(controllerPackage + File.separator + defaultController + ".py").exists()) {
//supportingFiles.add(new SupportingFile("controller.mustache",
// controllerPackage,
// defaultController + ".py")
//);
supportingFiles.add(new SupportingFile("__init__.mustache", supportingFiles.add(new SupportingFile("__init__.mustache",
controllerPackage, controllerPackage,
"__init__.py") "__init__.py")
@ -269,7 +265,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
} }
else { else {
// no tag found, use "default_controller" as the default // no tag found, use "default_controller" as the default
String tag = "default_controller"; String tag = "default";
operation.setTags(Arrays.asList(tag)); operation.setTags(Arrays.asList(tag));
controllerName = tag + "_controller"; controllerName = tag + "_controller";
} }

View File

@ -234,6 +234,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
setUseInheritance(Boolean.parseBoolean((String)additionalProperties.get(USE_INHERITANCE))); setUseInheritance(Boolean.parseBoolean((String)additionalProperties.get(USE_INHERITANCE)));
} else { } else {
supportsInheritance = true; supportsInheritance = true;
supportsMixins = true;
} }
if (additionalProperties.containsKey(EMIT_MODEL_METHODS)) { if (additionalProperties.containsKey(EMIT_MODEL_METHODS)) {
setEmitModelMethods(Boolean.parseBoolean((String)additionalProperties.get(EMIT_MODEL_METHODS))); setEmitModelMethods(Boolean.parseBoolean((String)additionalProperties.get(EMIT_MODEL_METHODS)));
@ -397,6 +398,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
public void setUseInheritance(boolean useInheritance) { public void setUseInheritance(boolean useInheritance) {
this.supportsInheritance = useInheritance; this.supportsInheritance = useInheritance;
this.supportsMixins = useInheritance;
} }
public void setEmitModelMethods(boolean emitModelMethods) { public void setEmitModelMethods(boolean emitModelMethods) {
@ -900,7 +902,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
// NOTE: can't use 'mandatory' as it is built from ModelImpl.getRequired(), which sorts names // NOTE: can't use 'mandatory' as it is built from ModelImpl.getRequired(), which sorts names
// alphabetically and in any case the document order of 'required' and 'properties' can differ. // alphabetically and in any case the document order of 'required' and 'properties' can differ.
List<CodegenProperty> required = new ArrayList<>(); List<CodegenProperty> required = new ArrayList<>();
List<CodegenProperty> allRequired = supportsInheritance ? new ArrayList<CodegenProperty>() : required; List<CodegenProperty> allRequired = supportsInheritance || supportsMixins ? new ArrayList<CodegenProperty>() : required;
cm.vendorExtensions.put("x-required", required); cm.vendorExtensions.put("x-required", required);
cm.vendorExtensions.put("x-all-required", allRequired); cm.vendorExtensions.put("x-all-required", allRequired);
@ -914,7 +916,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
} }
} }
if (supportsInheritance) { if (supportsInheritance || supportsMixins) {
for (CodegenProperty var : cm.allVars) { for (CodegenProperty var : cm.allVars) {
if (Boolean.TRUE.equals(var.required)) { if (Boolean.TRUE.equals(var.required)) {
allRequired.add(var); allRequired.add(var);

View File

@ -281,8 +281,8 @@ public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb // e.g. DefaultController => defaults_controller.rb
return underscore(name) + "_controllers"; return underscore(name) + "s_controller";
} }
@Override @Override

View File

@ -16,9 +16,8 @@ namespace {{packageName}}.Controllers
{ {{#operations}} { {{#operations}}
/// <summary> /// <summary>
/// {{description}} /// {{description}}
/// </summary>{{#description}}{{#basePath}} /// </summary>{{#description}}
[Route("{{{basePath}}}")] [Description("{{description}}")]{{/description}}
{{/basePath}}[Description("{{description}}")]{{/description}}
public class {{classname}}Controller : Controller public class {{classname}}Controller : Controller
{ {{#operation}} { {{#operation}}
@ -29,7 +28,7 @@ namespace {{packageName}}.Controllers
/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}{{#responses}} /// <param name="{{paramName}}">{{description}}</param>{{/allParams}}{{#responses}}
/// <response code="{{code}}">{{message}}</response>{{/responses}} /// <response code="{{code}}">{{message}}</response>{{/responses}}
[{{httpMethod}}] [{{httpMethod}}]
[Route("{{path}}")] [Route("{{basePathWithoutHost}}{{path}}")]
[SwaggerOperation("{{operationId}}")]{{#returnType}} [SwaggerOperation("{{operationId}}")]{{#returnType}}
[SwaggerResponse(200, type: typeof({{&returnType}}))]{{/returnType}} [SwaggerResponse(200, type: typeof({{&returnType}}))]{{/returnType}}
public virtual {{#returnType}}IActionResult{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) public virtual {{#returnType}}IActionResult{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}}({{#allParams}}{{>pathParam}}{{>queryParam}}{{>bodyParam}}{{>formParam}}{{>headerParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}})

View File

@ -4,7 +4,7 @@
class InitTables < ActiveRecord::Migration class InitTables < ActiveRecord::Migration
def change{{#models}}{{#model}} def change{{#models}}{{#model}}
create_table :{{classFilename}}, id: false do |t|{{#vars}}{{#isContainer}} create_table "{{classFilename}}".pluralize.to_sym, id: false do |t|{{#vars}}{{#isContainer}}
t.string :{{name}}{{/isContainer}}{{^isContainer}} t.string :{{name}}{{/isContainer}}{{^isContainer}}
t.{{datatype}} :{{{name}}}{{/isContainer}}{{/vars}} t.{{datatype}} :{{{name}}}{{/isContainer}}{{/vars}}

View File

@ -5,7 +5,7 @@
{{#models}}{{#model}} {{#models}}{{#model}}
class {{classname}} < ApplicationRecord class {{classname}} < ApplicationRecord
{{#requiredVars}} {{#requiredVars}}
validate_presence_of :{{name}} validates_presence_of :{{name}}
{{/requiredVars}}{{#vars}}{{#isListContainer}} {{/requiredVars}}{{#vars}}{{#isListContainer}}
serialize :{{name}}, Array{{/isListContainer}}{{#isMapContainer}} serialize :{{name}}, Array{{/isListContainer}}{{#isMapContainer}}
serialize :{{name}}, Hash{{/isMapContainer}}{{/vars}} serialize :{{name}}, Hash{{/isMapContainer}}{{/vars}}

View File

@ -1,5 +1,6 @@
package io.swagger.codegen; package io.swagger.codegen;
import io.swagger.models.Model;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
@ -187,6 +188,129 @@ public class CodegenTest {
Assert.assertEquals(op.discriminator, "className"); Assert.assertEquals(op.discriminator, "className");
} }
@Test(description = "handle simple composition")
public void simpleCompositionTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("SimpleComposition");
CodegenModel composed = codegen.fromModel("SimpleComposition", model, swagger.getDefinitions());
Assert.assertEquals(composed.vars.size(), 3);
Assert.assertEquals(composed.vars.get(0).baseName, "modelOneProp");
Assert.assertEquals(composed.vars.get(1).baseName, "modelTwoProp");
Assert.assertEquals(composed.vars.get(2).baseName, "simpleCompositionProp");
Assert.assertNull(composed.parent);
}
@Test(description = "handle multi level composition")
public void multiCompositionTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("CompositionOfSimpleComposition");
CodegenModel composed = codegen.fromModel("CompositionOfSimpleComposition", model, swagger.getDefinitions());
Assert.assertEquals(composed.vars.size(), 5);
Assert.assertEquals(composed.vars.get(0).baseName, "modelOneProp");
Assert.assertEquals(composed.vars.get(1).baseName, "modelTwoProp");
Assert.assertEquals(composed.vars.get(2).baseName, "simpleCompositionProp");
Assert.assertEquals(composed.vars.get(3).baseName, "modelThreeProp");
Assert.assertEquals(composed.vars.get(4).baseName, "compositionOfSimpleCompositionProp");
Assert.assertNull(composed.parent);
}
@Test(description = "handle simple inheritance")
public void simpleInheritanceTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("ChildOfSimpleParent");
CodegenModel child = codegen.fromModel("ChildOfSimpleParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 2);
Assert.assertEquals(child.vars.get(0).baseName, "modelOneProp");
Assert.assertEquals(child.vars.get(1).baseName, "childOfSimpleParentProp");
Assert.assertEquals(child.parent, "SimpleParent");
}
@Test(description = "handle multi level inheritance")
public void multiInheritanceTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("ChildOfChildOfSimpleParent");
CodegenModel child = codegen.fromModel("ChildOfChildOfSimpleParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 1);
Assert.assertEquals(child.vars.get(0).baseName, "childOfChildOfSimpleParentProp");
Assert.assertEquals(child.parent, "ChildOfSimpleParent");
}
@Test(description = "copy properties in multi level inheritance if supportsInheritance is false")
public void noSupportsInheritanceTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
final Model model = swagger.getDefinitions().get("ChildOfChildOfSimpleParent");
CodegenModel child = codegen.fromModel("ChildOfChildOfSimpleParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 5);
Assert.assertEquals(child.vars.get(0).baseName, "modelOneProp");
Assert.assertEquals(child.vars.get(1).baseName, "disc");
Assert.assertEquals(child.vars.get(2).baseName, "simpleParentProp");
Assert.assertEquals(child.vars.get(3).baseName, "childOfSimpleParentProp");
Assert.assertEquals(child.vars.get(4).baseName, "childOfChildOfSimpleParentProp");
Assert.assertEquals(child.parent, "ChildOfSimpleParent");
}
@Test(description = "don't copy interfaces properties if supportsMixins is true")
public void supportsMixinsTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
codegen.supportsMixins = true;
final Model model = swagger.getDefinitions().get("ChildOfChildOfSimpleParent");
CodegenModel child = codegen.fromModel("ChildOfChildOfSimpleParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 1);
Assert.assertEquals(child.vars.get(0).baseName, "childOfChildOfSimpleParentProp");
Assert.assertEquals(child.allVars.size(), 5);
Assert.assertEquals(child.allVars.get(0).baseName, "modelOneProp");
Assert.assertEquals(child.allVars.get(1).baseName, "disc");
Assert.assertEquals(child.allVars.get(2).baseName, "simpleParentProp");
Assert.assertEquals(child.allVars.get(3).baseName, "childOfSimpleParentProp");
Assert.assertEquals(child.allVars.get(4).baseName, "childOfChildOfSimpleParentProp");
Assert.assertEquals(child.parent, "ChildOfSimpleParent");
}
@Test(description = "handle inheritance from composed model")
public void inheritanceOfComposedModelTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("ChildOfComposedParent");
CodegenModel child = codegen.fromModel("ChildOfComposedParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 1);
Assert.assertEquals(child.vars.get(0).baseName, "childOfComposedParentProp");
Assert.assertEquals(child.parent, "ComposedParent");
}
@Test(description = "handle multi level inheritance from composed model")
public void multiInheritanceOfComposedModelTest() {
final Swagger swagger = parseAndPrepareSwagger("src/test/resources/2_0/allOfTest.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.supportsInheritance = true;
final Model model = swagger.getDefinitions().get("ChildOfChildOfComposedParent");
CodegenModel child = codegen.fromModel("ChildOfChildOfComposedParent", model, swagger.getDefinitions());
Assert.assertEquals(child.vars.size(), 1);
Assert.assertEquals(child.vars.get(0).baseName, "childOfChildOfComposedParentProp");
Assert.assertEquals(child.parent, "ChildOfComposedParent");
}
@Test(description = "use operation consumes and produces") @Test(description = "use operation consumes and produces")
public void localConsumesAndProducesTest() { public void localConsumesAndProducesTest() {
final Swagger model = parseAndPrepareSwagger("src/test/resources/2_0/globalConsumesAndProduces.json"); final Swagger model = parseAndPrepareSwagger("src/test/resources/2_0/globalConsumesAndProduces.json");

View File

@ -0,0 +1,104 @@
swagger: '2.0'
info:
version: 0.0.0
title: Simple API
paths:
/:
get:
responses:
200:
description: OK
definitions:
ModelOne:
type: object
properties:
modelOneProp:
type: string
ModelTwo:
type: object
properties:
modelTwoProp:
type: string
ModelThree:
type: object
properties:
modelThreeProp:
type: string
SimpleComposition:
allOf:
- $ref: '#/definitions/ModelOne'
- $ref: '#/definitions/ModelTwo'
- type: object
properties:
simpleCompositionProp:
type: string
CompositionOfSimpleComposition:
allOf:
- $ref: '#/definitions/SimpleComposition'
- $ref: '#/definitions/ModelThree'
- type: object
properties:
compositionOfSimpleCompositionProp:
type: string
SimpleParent:
type: object
discriminator: disc
properties:
disc:
type: string
simpleParentProp:
type: string
required: [disc]
ChildOfSimpleParent:
allOf:
- $ref: '#/definitions/ModelOne'
- $ref: '#/definitions/SimpleParent'
- type: object
properties:
childOfSimpleParentProp:
type: string
ChildOfChildOfSimpleParent:
allOf:
- $ref: '#/definitions/ChildOfSimpleParent'
- type: object
properties:
childOfChildOfSimpleParentProp:
type: string
ComposedParent:
allOf:
- $ref: '#/definitions/ModelOne'
- $ref: '#/definitions/ModelTwo'
- type: object
discriminator: disc
properties:
disc:
type: string
composedParentProp:
type: string
required: [disc]
ChildOfComposedParent:
allOf:
- $ref: '#/definitions/ComposedParent'
- type: object
properties:
childOfComposedParentProp:
type: string
ChildOfChildOfComposedParent:
allOf:
- $ref: '#/definitions/ChildOfComposedParent'
- type: object
properties:
childOfChildOfComposedParentProp:
type: string

View File

@ -48,7 +48,7 @@ namespace IO.Swagger.Controllers
/// <param name="body">Pet object that needs to be added to the store</param> /// <param name="body">Pet object that needs to be added to the store</param>
/// <response code="405">Invalid input</response> /// <response code="405">Invalid input</response>
[HttpPost] [HttpPost]
[Route("/pet")] [Route("/v2/pet")]
[SwaggerOperation("AddPet")] [SwaggerOperation("AddPet")]
public virtual void AddPet([FromBody]Pet body) public virtual void AddPet([FromBody]Pet body)
{ {
@ -64,7 +64,7 @@ namespace IO.Swagger.Controllers
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
/// <response code="400">Invalid pet value</response> /// <response code="400">Invalid pet value</response>
[HttpDelete] [HttpDelete]
[Route("/pet/{petId}")] [Route("/v2/pet/{petId}")]
[SwaggerOperation("DeletePet")] [SwaggerOperation("DeletePet")]
public virtual void DeletePet([FromRoute]long? petId, [FromHeader]string apiKey) public virtual void DeletePet([FromRoute]long? petId, [FromHeader]string apiKey)
{ {
@ -80,7 +80,7 @@ namespace IO.Swagger.Controllers
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
/// <response code="400">Invalid status value</response> /// <response code="400">Invalid status value</response>
[HttpGet] [HttpGet]
[Route("/pet/findByStatus")] [Route("/v2/pet/findByStatus")]
[SwaggerOperation("FindPetsByStatus")] [SwaggerOperation("FindPetsByStatus")]
[SwaggerResponse(200, type: typeof(List<Pet>))] [SwaggerResponse(200, type: typeof(List<Pet>))]
public virtual IActionResult FindPetsByStatus([FromQuery]List<string> status) public virtual IActionResult FindPetsByStatus([FromQuery]List<string> status)
@ -102,7 +102,7 @@ namespace IO.Swagger.Controllers
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
/// <response code="400">Invalid tag value</response> /// <response code="400">Invalid tag value</response>
[HttpGet] [HttpGet]
[Route("/pet/findByTags")] [Route("/v2/pet/findByTags")]
[SwaggerOperation("FindPetsByTags")] [SwaggerOperation("FindPetsByTags")]
[SwaggerResponse(200, type: typeof(List<Pet>))] [SwaggerResponse(200, type: typeof(List<Pet>))]
public virtual IActionResult FindPetsByTags([FromQuery]List<string> tags) public virtual IActionResult FindPetsByTags([FromQuery]List<string> tags)
@ -125,7 +125,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid ID supplied</response> /// <response code="400">Invalid ID supplied</response>
/// <response code="404">Pet not found</response> /// <response code="404">Pet not found</response>
[HttpGet] [HttpGet]
[Route("/pet/{petId}")] [Route("/v2/pet/{petId}")]
[SwaggerOperation("GetPetById")] [SwaggerOperation("GetPetById")]
[SwaggerResponse(200, type: typeof(Pet))] [SwaggerResponse(200, type: typeof(Pet))]
public virtual IActionResult GetPetById([FromRoute]long? petId) public virtual IActionResult GetPetById([FromRoute]long? petId)
@ -148,7 +148,7 @@ namespace IO.Swagger.Controllers
/// <response code="404">Pet not found</response> /// <response code="404">Pet not found</response>
/// <response code="405">Validation exception</response> /// <response code="405">Validation exception</response>
[HttpPut] [HttpPut]
[Route("/pet")] [Route("/v2/pet")]
[SwaggerOperation("UpdatePet")] [SwaggerOperation("UpdatePet")]
public virtual void UpdatePet([FromBody]Pet body) public virtual void UpdatePet([FromBody]Pet body)
{ {
@ -165,7 +165,7 @@ namespace IO.Swagger.Controllers
/// <param name="status">Updated status of the pet</param> /// <param name="status">Updated status of the pet</param>
/// <response code="405">Invalid input</response> /// <response code="405">Invalid input</response>
[HttpPost] [HttpPost]
[Route("/pet/{petId}")] [Route("/v2/pet/{petId}")]
[SwaggerOperation("UpdatePetWithForm")] [SwaggerOperation("UpdatePetWithForm")]
public virtual void UpdatePetWithForm([FromRoute]long? petId, [FromForm]string name, [FromForm]string status) public virtual void UpdatePetWithForm([FromRoute]long? petId, [FromForm]string name, [FromForm]string status)
{ {
@ -182,7 +182,7 @@ namespace IO.Swagger.Controllers
/// <param name="file">file to upload</param> /// <param name="file">file to upload</param>
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
[HttpPost] [HttpPost]
[Route("/pet/{petId}/uploadImage")] [Route("/v2/pet/{petId}/uploadImage")]
[SwaggerOperation("UploadFile")] [SwaggerOperation("UploadFile")]
[SwaggerResponse(200, type: typeof(ApiResponse))] [SwaggerResponse(200, type: typeof(ApiResponse))]
public virtual IActionResult UploadFile([FromRoute]long? petId, [FromForm]string additionalMetadata, [FromForm]System.IO.Stream file) public virtual IActionResult UploadFile([FromRoute]long? petId, [FromForm]string additionalMetadata, [FromForm]System.IO.Stream file)

View File

@ -49,7 +49,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid ID supplied</response> /// <response code="400">Invalid ID supplied</response>
/// <response code="404">Order not found</response> /// <response code="404">Order not found</response>
[HttpDelete] [HttpDelete]
[Route("/store/order/{orderId}")] [Route("/v2/store/order/{orderId}")]
[SwaggerOperation("DeleteOrder")] [SwaggerOperation("DeleteOrder")]
public virtual void DeleteOrder([FromRoute]string orderId) public virtual void DeleteOrder([FromRoute]string orderId)
{ {
@ -63,7 +63,7 @@ namespace IO.Swagger.Controllers
/// <remarks>Returns a map of status codes to quantities</remarks> /// <remarks>Returns a map of status codes to quantities</remarks>
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
[HttpGet] [HttpGet]
[Route("/store/inventory")] [Route("/v2/store/inventory")]
[SwaggerOperation("GetInventory")] [SwaggerOperation("GetInventory")]
[SwaggerResponse(200, type: typeof(Dictionary<string, int?>))] [SwaggerResponse(200, type: typeof(Dictionary<string, int?>))]
public virtual IActionResult GetInventory() public virtual IActionResult GetInventory()
@ -86,7 +86,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid ID supplied</response> /// <response code="400">Invalid ID supplied</response>
/// <response code="404">Order not found</response> /// <response code="404">Order not found</response>
[HttpGet] [HttpGet]
[Route("/store/order/{orderId}")] [Route("/v2/store/order/{orderId}")]
[SwaggerOperation("GetOrderById")] [SwaggerOperation("GetOrderById")]
[SwaggerResponse(200, type: typeof(Order))] [SwaggerResponse(200, type: typeof(Order))]
public virtual IActionResult GetOrderById([FromRoute]long? orderId) public virtual IActionResult GetOrderById([FromRoute]long? orderId)
@ -108,7 +108,7 @@ namespace IO.Swagger.Controllers
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
/// <response code="400">Invalid Order</response> /// <response code="400">Invalid Order</response>
[HttpPost] [HttpPost]
[Route("/store/order")] [Route("/v2/store/order")]
[SwaggerOperation("PlaceOrder")] [SwaggerOperation("PlaceOrder")]
[SwaggerResponse(200, type: typeof(Order))] [SwaggerResponse(200, type: typeof(Order))]
public virtual IActionResult PlaceOrder([FromBody]Order body) public virtual IActionResult PlaceOrder([FromBody]Order body)

View File

@ -48,7 +48,7 @@ namespace IO.Swagger.Controllers
/// <param name="body">Created user object</param> /// <param name="body">Created user object</param>
/// <response code="0">successful operation</response> /// <response code="0">successful operation</response>
[HttpPost] [HttpPost]
[Route("/user")] [Route("/v2/user")]
[SwaggerOperation("CreateUser")] [SwaggerOperation("CreateUser")]
public virtual void CreateUser([FromBody]User body) public virtual void CreateUser([FromBody]User body)
{ {
@ -63,7 +63,7 @@ namespace IO.Swagger.Controllers
/// <param name="body">List of user object</param> /// <param name="body">List of user object</param>
/// <response code="0">successful operation</response> /// <response code="0">successful operation</response>
[HttpPost] [HttpPost]
[Route("/user/createWithArray")] [Route("/v2/user/createWithArray")]
[SwaggerOperation("CreateUsersWithArrayInput")] [SwaggerOperation("CreateUsersWithArrayInput")]
public virtual void CreateUsersWithArrayInput([FromBody]List<User> body) public virtual void CreateUsersWithArrayInput([FromBody]List<User> body)
{ {
@ -78,7 +78,7 @@ namespace IO.Swagger.Controllers
/// <param name="body">List of user object</param> /// <param name="body">List of user object</param>
/// <response code="0">successful operation</response> /// <response code="0">successful operation</response>
[HttpPost] [HttpPost]
[Route("/user/createWithList")] [Route("/v2/user/createWithList")]
[SwaggerOperation("CreateUsersWithListInput")] [SwaggerOperation("CreateUsersWithListInput")]
public virtual void CreateUsersWithListInput([FromBody]List<User> body) public virtual void CreateUsersWithListInput([FromBody]List<User> body)
{ {
@ -94,7 +94,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid username supplied</response> /// <response code="400">Invalid username supplied</response>
/// <response code="404">User not found</response> /// <response code="404">User not found</response>
[HttpDelete] [HttpDelete]
[Route("/user/{username}")] [Route("/v2/user/{username}")]
[SwaggerOperation("DeleteUser")] [SwaggerOperation("DeleteUser")]
public virtual void DeleteUser([FromRoute]string username) public virtual void DeleteUser([FromRoute]string username)
{ {
@ -111,7 +111,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid username supplied</response> /// <response code="400">Invalid username supplied</response>
/// <response code="404">User not found</response> /// <response code="404">User not found</response>
[HttpGet] [HttpGet]
[Route("/user/{username}")] [Route("/v2/user/{username}")]
[SwaggerOperation("GetUserByName")] [SwaggerOperation("GetUserByName")]
[SwaggerResponse(200, type: typeof(User))] [SwaggerResponse(200, type: typeof(User))]
public virtual IActionResult GetUserByName([FromRoute]string username) public virtual IActionResult GetUserByName([FromRoute]string username)
@ -134,7 +134,7 @@ namespace IO.Swagger.Controllers
/// <response code="200">successful operation</response> /// <response code="200">successful operation</response>
/// <response code="400">Invalid username/password supplied</response> /// <response code="400">Invalid username/password supplied</response>
[HttpGet] [HttpGet]
[Route("/user/login")] [Route("/v2/user/login")]
[SwaggerOperation("LoginUser")] [SwaggerOperation("LoginUser")]
[SwaggerResponse(200, type: typeof(string))] [SwaggerResponse(200, type: typeof(string))]
public virtual IActionResult LoginUser([FromQuery]string username, [FromQuery]string password) public virtual IActionResult LoginUser([FromQuery]string username, [FromQuery]string password)
@ -154,7 +154,7 @@ namespace IO.Swagger.Controllers
/// <remarks></remarks> /// <remarks></remarks>
/// <response code="0">successful operation</response> /// <response code="0">successful operation</response>
[HttpGet] [HttpGet]
[Route("/user/logout")] [Route("/v2/user/logout")]
[SwaggerOperation("LogoutUser")] [SwaggerOperation("LogoutUser")]
public virtual void LogoutUser() public virtual void LogoutUser()
{ {
@ -171,7 +171,7 @@ namespace IO.Swagger.Controllers
/// <response code="400">Invalid user supplied</response> /// <response code="400">Invalid user supplied</response>
/// <response code="404">User not found</response> /// <response code="404">User not found</response>
[HttpPut] [HttpPut]
[Route("/user/{username}")] [Route("/v2/user/{username}")]
[SwaggerOperation("UpdateUser")] [SwaggerOperation("UpdateUser")]
public virtual void UpdateUser([FromRoute]string username, [FromBody]User body) public virtual void UpdateUser([FromRoute]string username, [FromBody]User body)
{ {

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// Describes the result of uploading an image resource
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class ApiResponse : IEquatable<ApiResponse> public partial class ApiResponse : IEquatable<ApiResponse>

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// A category for a pet
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class Category : IEquatable<Category> public partial class Category : IEquatable<Category>

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// An order for a pets from the pet store
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class Order : IEquatable<Order> public partial class Order : IEquatable<Order>

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// A pet for sale in the pet store
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class Pet : IEquatable<Pet> public partial class Pet : IEquatable<Pet>

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// A tag for a pet
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class Tag : IEquatable<Tag> public partial class Tag : IEquatable<Tag>

View File

@ -33,7 +33,7 @@ using Newtonsoft.Json;
namespace IO.Swagger.Models namespace IO.Swagger.Models
{ {
/// <summary> /// <summary>
/// /// A User who is purchasing from the pet store
/// </summary> /// </summary>
[DataContract] [DataContract]
public partial class User : IEquatable<User> public partial class User : IEquatable<User>

View File

@ -644,6 +644,8 @@ definitions:
complete: complete:
type: "boolean" type: "boolean"
default: false default: false
title: "Pet Order"
description: "An order for a pets from the pet store"
xml: xml:
name: "Order" name: "Order"
Category: Category:
@ -654,6 +656,8 @@ definitions:
format: "int64" format: "int64"
name: name:
type: "string" type: "string"
title: "Pet catehgry"
description: "A category for a pet"
xml: xml:
name: "Category" name: "Category"
User: User:
@ -678,6 +682,8 @@ definitions:
type: "integer" type: "integer"
format: "int32" format: "int32"
description: "User Status" description: "User Status"
title: "a User"
description: "A User who is purchasing from the pet store"
xml: xml:
name: "User" name: "User"
Tag: Tag:
@ -688,6 +694,8 @@ definitions:
format: "int64" format: "int64"
name: name:
type: "string" type: "string"
title: "Pet Tag"
description: "A tag for a pet"
xml: xml:
name: "Tag" name: "Tag"
Pet: Pet:
@ -725,6 +733,8 @@ definitions:
- "available" - "available"
- "pending" - "pending"
- "sold" - "sold"
title: "a Pet"
description: "A pet for sale in the pet store"
xml: xml:
name: "Pet" name: "Pet"
ApiResponse: ApiResponse:
@ -737,6 +747,8 @@ definitions:
type: "string" type: "string"
message: message:
type: "string" type: "string"
title: "An uploaded response"
description: "Describes the result of uploading an image resource"
externalDocs: externalDocs:
description: "Find out more about Swagger" description: "Find out more about Swagger"
url: "http://swagger.io" url: "http://swagger.io"

View File

@ -23,8 +23,8 @@ limitations under the License.
class Pet < ApplicationRecord class Pet < ApplicationRecord
validate_presence_of :name validates_presence_of :name
validate_presence_of :photo_urls validates_presence_of :photo_urls
serialize :photo_urls, Array serialize :photo_urls, Array
serialize :tags, Array serialize :tags, Array

View File

@ -23,7 +23,7 @@ limitations under the License.
class InitTables < ActiveRecord::Migration class InitTables < ActiveRecord::Migration
def change def change
create_table :api_response, id: false do |t| create_table "api_response".pluralize.to_sym, id: false do |t|
t.integer :code t.integer :code
t.string :type t.string :type
t.string :message t.string :message
@ -31,14 +31,14 @@ class InitTables < ActiveRecord::Migration
t.timestamps t.timestamps
end end
create_table :category, id: false do |t| create_table "category".pluralize.to_sym, id: false do |t|
t.integer :id t.integer :id
t.string :name t.string :name
t.timestamps t.timestamps
end end
create_table :order, id: false do |t| create_table "order".pluralize.to_sym, id: false do |t|
t.integer :id t.integer :id
t.integer :pet_id t.integer :pet_id
t.integer :quantity t.integer :quantity
@ -49,7 +49,7 @@ class InitTables < ActiveRecord::Migration
t.timestamps t.timestamps
end end
create_table :pet, id: false do |t| create_table "pet".pluralize.to_sym, id: false do |t|
t.integer :id t.integer :id
t.string :category t.string :category
t.string :name t.string :name
@ -60,14 +60,14 @@ class InitTables < ActiveRecord::Migration
t.timestamps t.timestamps
end end
create_table :tag, id: false do |t| create_table "tag".pluralize.to_sym, id: false do |t|
t.integer :id t.integer :id
t.string :name t.string :name
t.timestamps t.timestamps
end end
create_table :user, id: false do |t| create_table "user".pluralize.to_sym, id: false do |t|
t.integer :id t.integer :id
t.string :username t.string :username
t.string :first_name t.string :first_name