diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenOperation.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenOperation.java index 4535115ef1c..c341cdb3cd0 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenOperation.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenOperation.java @@ -1,6 +1,7 @@ package io.swagger.codegen; import io.swagger.models.ExternalDocs; +import io.swagger.models.Tag; import java.util.ArrayList; import java.util.HashSet; @@ -28,7 +29,7 @@ public class CodegenOperation { public List headerParams = new ArrayList(); public List formParams = new ArrayList(); public List authMethods; - public List tags; + public List tags; public List responses = new ArrayList(); public Set imports = new HashSet(); public List> examples; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index dee8caaadd3..bb3817896f1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -1965,7 +1965,6 @@ public class DefaultCodegen { op.summary = escapeText(operation.getSummary()); op.unescapedNotes = operation.getDescription(); op.notes = escapeText(operation.getDescription()); - op.tags = operation.getTags(); op.hasConsumes = false; op.hasProduces = false; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index 665b6dfd5dd..728b9578897 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -751,11 +751,37 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { if (System.getProperty("debugOperations") != null) { LOGGER.info("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n"); } - List tags = operation.getTags(); - if (tags == null) { - tags = new ArrayList(); - tags.add("default"); + List tags = new ArrayList(); + + List tagNames = operation.getTags(); + List swaggerTags = swagger.getTags(); + if (tagNames != null) { + if (swaggerTags == null) { + for (String tagName : tagNames) { + tags.add(new Tag().name(tagName)); + } + } else { + for (String tagName : tagNames) { + boolean foundTag = false; + for (Tag tag : swaggerTags) { + if (tag.getName().equals(tagName)) { + tags.add(tag); + foundTag = true; + break; + } + } + + if (!foundTag) { + tags.add(new Tag().name(tagName)); + } + } + } } + + if (tags.isEmpty()) { + tags.add(new Tag().name("default")); + } + /* build up a set of parameter "ids" defined at the operation level per the swagger 2.0 spec "A unique parameter is defined by a combination of a name and location" @@ -778,12 +804,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { } } - for (String tag : tags) { + for (Tag tag : tags) { try { CodegenOperation codegenOperation = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions(), swagger); - codegenOperation.tags = new ArrayList(); - codegenOperation.tags.add(config.sanitizeTag(tag)); - config.addOperationToGroup(config.sanitizeTag(tag), resourcePath, operation, codegenOperation, operations); + codegenOperation.tags = new ArrayList(tags); + config.addOperationToGroup(config.sanitizeTag(tag.getName()), resourcePath, operation, codegenOperation, operations); List>> securities = operation.getSecurity(); if (securities == null && swagger.getSecurity() != null) { diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/DefaultGeneratorTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/DefaultGeneratorTest.java index 9f66283fbde..c17133e8c15 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/DefaultGeneratorTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/DefaultGeneratorTest.java @@ -1,7 +1,9 @@ package io.swagger.codegen; import io.swagger.codegen.languages.JavaClientCodegen; +import io.swagger.models.ExternalDocs; import io.swagger.models.Swagger; +import io.swagger.models.Tag; import io.swagger.parser.SwaggerParser; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; @@ -14,10 +16,7 @@ import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static io.swagger.codegen.CodegenConstants.TEMPLATE_DIR; import static java.nio.charset.StandardCharsets.UTF_8; @@ -281,6 +280,236 @@ public class DefaultGeneratorTest { } } + @Test + public void testResolveTagsAgainstSwaggerTagsDefinition() { + final File output = folder.getRoot(); + + String spec = + "swagger: '2.0'\n" + + "info:\n" + + " version: 1.0.0\n" + + " title: Swagger Petstore\n" + + "tags:\n" + + " - name: pet\n" + + " description: Everything about your Pets\n" + + " externalDocs:\n" + + " description: Find out more\n" + + " url: 'http://swagger.io'\n" + + " x-vendor-ext: 'tag'\n" + + " - name: store\n" + + " description: Access to Petstore orders\n" + + " - name: user\n" + + " description: Operations about user\n" + + " externalDocs:\n" + + " x-vendor-ext: 'foo'\n" + + "paths:\n" + + " /pet:\n" + + " get:\n" + + " tags:\n" + + " - pet\n" + + " - store\n" + + " - user\n" + + " responses:\n" + + " '200':\n" + + " description: OK"; + + final List expectedTags = new ArrayList(); + expectedTags.add(new Tag().name("pet").description("Everything about your Pets").externalDocs(new ExternalDocs().description("Find out more").url("http://swagger.io"))); + expectedTags.add(new Tag().name("store").description("Access to Petstore orders")); + expectedTags.add(new Tag().name("user").description("Operations about user").externalDocs(new ExternalDocs())); + + expectedTags.get(0).getVendorExtensions().put("x-vendor-ext", "tag"); + expectedTags.get(2).getExternalDocs().getVendorExtensions().put("x-vendor-ext", "foo"); + + final Swagger swagger = new SwaggerParser().readWithInfo(spec).getSwagger(); + CodegenConfig codegenConfig = new JavaClientCodegen(); + codegenConfig.setOutputDir(output.getAbsolutePath()); + + ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).swagger(swagger).config(codegenConfig); + + DefaultGenerator generator = new DefaultGenerator(); + generator.opts(clientOptInput); + + Map> paths = generator.processPaths(swagger.getPaths()); + assertEquals(3, paths.size()); + + List sanitizedTags = Arrays.asList("Pet", "Store", "User"); + for (String tag : sanitizedTags) { + List operations = paths.get(tag); + assertNotNull(operations); + for (CodegenOperation operation : operations) { + assertOperationHasTags(operation, expectedTags); + } + } + } + + @Test + public void testResolveTagsNoSwaggerTagsDefinition() { + final File output = folder.getRoot(); + + String spec = + "swagger: '2.0'\n" + + "info:\n" + + " version: 1.0.0\n" + + " title: Swagger Petstore\n" + + "paths:\n" + + " /pet:\n" + + " get:\n" + + " tags:\n" + + " - pet\n" + + " - store\n" + + " - user\n" + + " responses:\n" + + " '200':\n" + + " description: OK"; + + final List expectedTags = new ArrayList(); + expectedTags.add(new Tag().name("pet")); + expectedTags.add(new Tag().name("store")); + expectedTags.add(new Tag().name("user")); + + final Swagger swagger = new SwaggerParser().readWithInfo(spec).getSwagger(); + CodegenConfig codegenConfig = new JavaClientCodegen(); + codegenConfig.setOutputDir(output.getAbsolutePath()); + + ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).swagger(swagger).config(codegenConfig); + + DefaultGenerator generator = new DefaultGenerator(); + generator.opts(clientOptInput); + + Map> paths = generator.processPaths(swagger.getPaths()); + assertEquals(3, paths.size()); + + List sanitizedTags = Arrays.asList("Pet", "Store", "User"); + for (String tag : sanitizedTags) { + List operations = paths.get(tag); + assertNotNull(operations); + for (CodegenOperation operation : operations) { + assertOperationHasTags(operation, expectedTags); + } + } + } + + @Test + public void testResolveTagsNoTagsDefined() { + final File output = folder.getRoot(); + + String spec = + "swagger: '2.0'\n" + + "info:\n" + + " version: 1.0.0\n" + + " title: Swagger Petstore\n" + + "paths:\n" + + " /pet:\n" + + " get:\n" + + " responses:\n" + + " '200':\n" + + " description: OK"; + + final List expectedTags = new ArrayList(); + expectedTags.add(new Tag().name("default")); + + final Swagger swagger = new SwaggerParser().readWithInfo(spec).getSwagger(); + CodegenConfig codegenConfig = new JavaClientCodegen(); + codegenConfig.setOutputDir(output.getAbsolutePath()); + + ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).swagger(swagger).config(codegenConfig); + + DefaultGenerator generator = new DefaultGenerator(); + generator.opts(clientOptInput); + + Map> paths = generator.processPaths(swagger.getPaths()); + assertEquals(1, paths.size()); + + List sanitizedTags = Collections.singletonList("Default"); + for (String tag : sanitizedTags) { + List operations = paths.get(tag); + assertNotNull(operations); + for (CodegenOperation operation : operations) { + assertOperationHasTags(operation, expectedTags); + } + } + } + + @Test + public void testResolveTagNotDefinedInSwaggerTagsDefinition() { + final File output = folder.getRoot(); + + String spec = + "swagger: '2.0'\n" + + "info:\n" + + " version: 1.0.0\n" + + " title: Swagger Petstore\n" + + "tags:\n" + + " - name: pet\n" + + " description: Everything about your Pets\n" + + "paths:\n" + + " /pet:\n" + + " get:\n" + + " tags:\n" + + " - pet\n" + + " - store\n" + // Not defined above + " - user\n" + // Not defined above + " responses:\n" + + " '200':\n" + + " description: OK"; + + final List expectedTags = new ArrayList(); + expectedTags.add(new Tag().name("pet").description("Everything about your Pets")); + expectedTags.add(new Tag().name("store")); + expectedTags.add(new Tag().name("user")); + + final Swagger swagger = new SwaggerParser().readWithInfo(spec).getSwagger(); + CodegenConfig codegenConfig = new JavaClientCodegen(); + codegenConfig.setOutputDir(output.getAbsolutePath()); + + ClientOptInput clientOptInput = new ClientOptInput().opts(new ClientOpts()).swagger(swagger).config(codegenConfig); + + DefaultGenerator generator = new DefaultGenerator(); + generator.opts(clientOptInput); + + Map> paths = generator.processPaths(swagger.getPaths()); + assertEquals(3, paths.size()); + + List sanitizedTags = Arrays.asList("Pet", "Store", "User"); + for (String tag : sanitizedTags) { + List operations = paths.get(tag); + assertNotNull(operations); + for (CodegenOperation operation : operations) { + assertOperationHasTags(operation, expectedTags); + } + } + } + + private void assertOperationHasTags(CodegenOperation op, List expectedTags) { + assertNotNull(op.tags); + assertEquals(op.tags.size(), expectedTags.size()); + + for (Tag tag : expectedTags) { + Tag foundTag = null; + + for (Tag opTag : op.tags) { + if (tag.getName().equals(opTag.getName())) { + foundTag = opTag; + break; + } + } + + if (foundTag == null) { + fail("Expected tag '" + tag.getName() + "' was not found on operation " + op.operationId); + } + + assertEquals(tag, foundTag); + if (!tag.getVendorExtensions().isEmpty()) { + assertEquals(tag.getVendorExtensions(), foundTag.getVendorExtensions()); + } + + if (tag.getExternalDocs() != null && !tag.getExternalDocs().getVendorExtensions().isEmpty()) { + assertEquals(tag.getExternalDocs().getVendorExtensions(), foundTag.getExternalDocs().getVendorExtensions()); + } + } + } + private static void changeContent(File file) throws IOException { Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), UTF_8)); out.write(TEST_SKIP_OVERWRITE);