Skip to content

Commit

Permalink
Merge pull request #1747 from wing328/add_golang
Browse files Browse the repository at this point in the history
[Go] Add Go API client generator
  • Loading branch information
wing328 committed Jan 22, 2016
2 parents 03b463b + 20e531d commit 5b6d224
Show file tree
Hide file tree
Showing 17 changed files with 1,298 additions and 0 deletions.
31 changes: 31 additions & 0 deletions bin/go-petstore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh

SCRIPT="$0"

while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done

if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi

executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"

if [ ! -f "$executable" ]
then
mvn clean package
fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/go -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l go -o samples/client/petstore/go"

java $JAVA_OPTS -jar $executable $ags
10 changes: 10 additions & 0 deletions bin/windows/go-petstore.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar

If Not Exist %executable% (
mvn clean package
)

set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\go -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l go -o samples\client\petstore\go

java %JAVA_OPTS% -jar %executable% %ags%
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package io.swagger.codegen.languages;

import io.swagger.codegen.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;

import java.io.File;
import java.util.*;

import org.apache.commons.lang.StringUtils;

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

public class GoClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(GoClientCodegen.class);

protected String packageName = "swagger";
protected String packageVersion = "1.0.0";

public CodegenType getTag() {
return CodegenType.CLIENT;
}

public String getName() {
return "go";
}

public String getHelp() {
return "Generates a Go client library (beta).";
}

public GoClientCodegen() {
super();
outputFolder = "generated-code/go";
modelTemplateFiles.put("model.mustache", ".go");
apiTemplateFiles.put("api.mustache", ".go");
templateDir = "go";

reservedWords = new HashSet<String> (
Arrays.asList(
"break", "default", "func", "interface", "select",
"case", "defer", "go", "map", "struct",
"chan", "else", "goto", "package", "switch",
"const", "fallthrough", "if", "range", "type",
"continue", "for", "import", "return", "var")
);

defaultIncludes = new HashSet<String>(
Arrays.asList(
"map",
"array")
);

languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"string",
"bool",
"uint",
"uint32",
"uint64",
"int",
"int32",
"int64",
"float32",
"float64",
"complex64",
"complex128",
"rune",
"byte")
);

instantiationTypes.clear();
/*instantiationTypes.put("array", "GoArray");
instantiationTypes.put("map", "GoMap");*/

typeMapping.clear();
typeMapping.put("integer", "int32");
typeMapping.put("long", "int64");
typeMapping.put("float", "float32");
typeMapping.put("double", "float64");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "string");
typeMapping.put("Date", "time.Time");
typeMapping.put("DateTime", "time.Time");
typeMapping.put("password", "string");
typeMapping.put("File", "*os.File");
typeMapping.put("file", "*os.File");
// map binary to string as a workaround
// the correct solution is to use []byte
typeMapping.put("binary", "string");

importMapping = new HashMap<String, String>();
importMapping.put("time.Time", "time");
importMapping.put("*os.File", "os");

cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Go package name (convention: lowercase).")
.defaultValue("swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Go package version.")
.defaultValue("1.0.0"));

}

@Override
public void processOpts() {
//super.processOpts();

if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
}
else {
setPackageName("swagger");
}

if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
else {
setPackageVersion("1.0.0");
}

additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);

modelPackage = packageName;
apiPackage = packageName;

supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}

@Override
public String escapeReservedWord(String name) {
return "_" + name;
}

@Override
public String apiFileFolder() {
return outputFolder + File.separator + packageName;
}

public String modelFileFolder() {
return outputFolder + File.separator + packageName;
}

@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");

// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;

// camelize (lower first character) the variable name
// pet_id => PetId
name = camelize(name);

// for reserved word or word starting with number, append _
if(reservedWords.contains(name) || name.matches("^\\d.*"))
name = escapeReservedWord(name);

return name;
}

@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}

@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if(reservedWords.contains(name))
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");

// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}

@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}

@Override
public String getTypeDeclaration(Property p) {
if(p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return "[]" + getTypeDeclaration(inner);
}
else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();

return getSwaggerType(p) + "[string]" + getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}

@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(languageSpecificPrimitives.contains(type))
return (type);
}
else
type = swaggerType;
return type;
}

@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if(reservedWords.contains(operationId))
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");

return camelize(operationId);
}

@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
@SuppressWarnings("unchecked")
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
@SuppressWarnings("unchecked")
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
for (CodegenOperation operation : operations) {
// http method verb conversion (e.g. PUT => Put)
operation.httpMethod = camelize(operation.httpMethod.toLowerCase());
}

// remove model imports to avoid error
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
if (imports == null)
return objs;

Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(apiPackage()))
iterator.remove();
}

return objs;
}

@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// remove model imports to avoid error
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
final String prefix = modelPackage();
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix))
iterator.remove();
}
return objs;
}

@Override
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}

public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ io.swagger.codegen.languages.CSharpClientCodegen
io.swagger.codegen.languages.DartClientCodegen
io.swagger.codegen.languages.FlashClientCodegen
io.swagger.codegen.languages.FlaskConnexionCodegen
io.swagger.codegen.languages.GoClientCodegen
io.swagger.codegen.languages.JavaClientCodegen
io.swagger.codegen.languages.JavascriptClientCodegen
io.swagger.codegen.languages.JaxRSServerCodegen
Expand Down
12 changes: 12 additions & 0 deletions modules/swagger-codegen/src/main/resources/go/README.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Go API client for {{packageName}}

## Overview
This API client was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [swagger-spec](https://github.com/swagger-api/swagger-spec) from a remote server, you can easily generate an API client.


## Installation
Put the package under your project folder and add the following in import:
```
"./{{packageName}}"
```

Loading

0 comments on commit 5b6d224

Please sign in to comment.