Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
package io.swagger.codegen.languages;

import io.swagger.codegen.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;

import java.util.*;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

public abstract class AbstractGoCodegen extends DefaultCodegen implements CodegenConfig {

protected static Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
Expand Down Expand Up @@ -78,7 +87,6 @@ public AbstractGoCodegen() {
typeMapping.put("binary", "string");
typeMapping.put("ByteArray", "string");
typeMapping.put("object", "interface{}");
typeMapping.put("UUID", "string");

importMapping = new HashMap<String, String>();

Expand Down Expand Up @@ -399,18 +407,20 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {
}
}
}

// recursively add import for mapping one type to multiple imports
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
if (recursiveImports == null)
return objs;

ListIterator<Map<String, String>> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
if (recursiveImports != null) {
objs.put("hasImport", !recursiveImports.isEmpty());

ListIterator<Map<String, String>> listIterator = imports.listIterator();
while (listIterator.hasNext()) {
String _import = listIterator.next().get("import");
// if the import package happens to be found in the importMapping (key)
// add the corresponding import package to the list
if (importMapping.containsKey(_import)) {
listIterator.add(createMapping("import", importMapping.get(_import)));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{{>partial_header}}
package {{packageName}}
{{#models}}{{#imports}}
import ({{/imports}}{{#imports}}
"{{import}}"{{/imports}}{{#imports}}
{{#models}}{{#hasImport}}
import ({{#imports}}
"{{import}}"{{/imports}}
)
{{/imports}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
{{/hasImport}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
type {{{name}}} {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}

// List of {{{name}}}
Expand Down
8 changes: 4 additions & 4 deletions modules/swagger-codegen/src/main/resources/go/model.mustache
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{{>partial_header}}
package {{packageName}}
{{#models}}{{#imports}}
import ({{/imports}}{{#imports}}
"{{import}}"{{/imports}}{{#imports}}
{{#models}}{{#hasImport}}
import ({{#imports}}
"{{import}}"{{/imports}}
)
{{/imports}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
{{/hasImport}}{{#model}}{{#isEnum}}{{#description}}// {{{classname}}} : {{{description}}}{{/description}}
type {{{classname}}} {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}

// List of {{{name}}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
package io.swagger.codegen.go;

import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.ClientOpts;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.languages.GoClientCodegen;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import io.swagger.parser.util.ParseOptions;
import org.junit.rules.TemporaryFolder;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.testng.reporters.Files;

import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.languages.GoClientCodegen;
import java.io.File;
import java.io.IOException;

import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

public class GoClientCodegenTest {

Expand Down Expand Up @@ -37,4 +54,97 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
Assert.assertEquals(codegen.isHideGenerationTimestamp(), false);
}

public static class Issue11775Test {

private static final String EXPECTED_MODEL = "package swagger\n" +
"\n" +
"import (\n" +
"\t\"github.com/google/uuid\"\n" +
"\t\"time\"\n" +
")\n" +
"\n" +
"type PetDto struct {\n" +
"\t// The creation timestamp\n" +
"\tCreatedAt time.Time `json:\"createdAt,omitempty\"`\n" +
"\t// The user who created\n" +
"\tCreatedBy *uuid.UUID `json:\"createdBy,omitempty\"`\n" +
"\t// The ID\n" +
"\tId *uuid.UUID `json:\"id,omitempty\"`\n" +
"\t// The name of the pet\n" +
"\tName string `json:\"name,omitempty\"`\n" +
"}";

private static final String EXPECTED_MODEL_WITH_NESTED_IMPORTS = "import (\n" +
"import (\n" +
"\t\"github.com/google/uuid\"\n" +
"\t\"time\"\n" +
")\n" +
"\n" +
")";

private static final TemporaryFolder TMP_FOLDER = new TemporaryFolder();

private CodegenConfig codegenConfig;
private Swagger swagger;

@BeforeClass
public void init() {
final ParseOptions parseOptions = new ParseOptions();
parseOptions.setFlatten(true);

swagger = new SwaggerParser().read("2_0/go/petWithGoogleUuid.json", null, parseOptions);

codegenConfig = new GoClientCodegen();
codegenConfig.typeMapping().put("UUID", "uuid.UUID");
codegenConfig.importMapping().put("uuid.UUID", "github.com/google/uuid");
}

@BeforeMethod
public void setUp() throws Exception {
TMP_FOLDER.create();
}

@AfterMethod
public void tearDown() {
TMP_FOLDER.delete();
}

@Test(description = "generate model with many imports")
public void testIssue11775() throws Exception {
codegenConfig.setOutputDir(TMP_FOLDER.getRoot().getAbsolutePath());

final ClientOptInput clientOptInput = new ClientOptInput()
.opts(new ClientOpts()).swagger(swagger).config(codegenConfig);

new DefaultGenerator().opts(clientOptInput).generate();

final File model = new File(TMP_FOLDER.getRoot(), "model_pet_dto.go");
assertTrue(model.exists());
assertTrue(containsString(model, EXPECTED_MODEL));
}

@Test(description = "generate invalid model caused by nested imports")
public void testIssue11775WithNestedImport() throws Exception {
codegenConfig.setOutputDir(TMP_FOLDER.getRoot().getAbsolutePath());

final ClientOptInput clientOptInput = new ClientOptInput()
.opts(new ClientOpts()).swagger(swagger).config(codegenConfig);

new DefaultGenerator().opts(clientOptInput).generate();

final File model = new File(TMP_FOLDER.getRoot(), "model_pet_dto.go");
assertTrue(model.exists());
assertFalse(containsString(model, EXPECTED_MODEL_WITH_NESTED_IMPORTS));
}

private static boolean containsString(final File file, final String text) throws IOException {
return trim(Files.readFile(file)).contains(trim(text));
}

private static String trim(final String value) {
return value.replaceAll("[ \n\r\t]", "");
}

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.swagger.codegen.go;

import com.google.common.collect.Sets;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.DefaultCodegen;
Expand All @@ -13,8 +14,7 @@
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;

import com.google.common.collect.Sets;
import io.swagger.models.properties.UUIDProperty;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
Expand Down Expand Up @@ -74,6 +74,62 @@ public void simpleModelTest() {
Assert.assertTrue(property3.isNotContainer);
}

@Test(description = "convert a model with custom type-mappings and import-mappings")
public void customTypedPropertyTest() {
final Model model = new ModelImpl()
.description("a model with custom type (uuid.UUID from google)")
.property("id", new UUIDProperty())
.property("name", new StringProperty())
.property("createdAt", new DateTimeProperty())
.required("id")
.required("name");
final DefaultCodegen codegen = new GoClientCodegen();

codegen.typeMapping().put("UUID", "uuid.UUID");
codegen.importMapping().put("uuid.UUID", "github.com/google/uuid");

final CodegenModel cm = codegen.fromModel("sample", model);

Assert.assertEquals(cm.name, "sample");
Assert.assertEquals(cm.classname, "Sample");
Assert.assertEquals(cm.description, "a model with custom type (uuid.UUID from google)");
Assert.assertEquals(cm.vars.size(), 3);
Assert.assertEquals(cm.imports.size(), 2);

final CodegenProperty property1 = cm.vars.get(0);
Assert.assertEquals(property1.baseName, "id");
Assert.assertEquals(property1.datatype, "uuid.UUID");
Assert.assertEquals(property1.name, "Id");
Assert.assertEquals(property1.defaultValue, "null");
Assert.assertEquals(property1.baseType, "uuid.UUID");
Assert.assertTrue(property1.hasMore);
Assert.assertTrue(property1.required);
Assert.assertFalse(property1.isPrimitiveType);
Assert.assertTrue(property1.isNotContainer);

final CodegenProperty property2 = cm.vars.get(1);
Assert.assertEquals(property2.baseName, "name");
Assert.assertEquals(property2.datatype, "string");
Assert.assertEquals(property2.name, "Name");
Assert.assertEquals(property2.defaultValue, "null");
Assert.assertEquals(property2.baseType, "string");
Assert.assertTrue(property2.hasMore);
Assert.assertTrue(property2.required);
Assert.assertTrue(property2.isPrimitiveType);
Assert.assertTrue(property2.isNotContainer);

final CodegenProperty property3 = cm.vars.get(2);
Assert.assertEquals(property3.baseName, "createdAt");
Assert.assertEquals(property3.complexType, "time.Time");
Assert.assertEquals(property3.datatype, "time.Time");
Assert.assertEquals(property3.name, "CreatedAt");
Assert.assertEquals(property3.defaultValue, "null");
Assert.assertEquals(property3.baseType, "time.Time");
Assert.assertFalse(property3.hasMore);
Assert.assertFalse(property3.required);
Assert.assertTrue(property3.isNotContainer);
}

@Test(description = "convert a model with list property")
public void listPropertyTest() {
final Model model = new ModelImpl()
Expand Down
Loading