Skip to content
Merged
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
31 changes: 31 additions & 0 deletions bin/lagomScalaApi-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/lagomScalaApi -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l scala-lagomApi -o samples/server/petstore/lagomScalaApi"

java $JAVA_OPTS -jar $executable $ags
10 changes: 10 additions & 0 deletions bin/windows/lagomScalaApi-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
)

REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.yaml -l scala-lagomApi -o samples\server\petstore\scala-lagomApi

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

import io.swagger.codegen.*;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

public class ScalaLagomServerCodegen extends AbstractScalaCodegen implements CodegenConfig {

private String authScheme = "";
private boolean authPreemptive=false;
protected String groupId = "io.swagger";
protected String artifactId = "scala-lagomApi";
protected String artifactVersion = "1.0.0";

public ScalaLagomServerCodegen() {
super();
outputFolder = "generated-code/scala-lagomApi";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
embeddedTemplateDir = templateDir = "lagomScalaApi";
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";

setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"path", "contentTypes", "contentType", "queryParams", "headerParams",
"formParams", "postBody", "mp", "basePath", "apiInvoker",

// scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
);

additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("authScheme", authScheme);
additionalProperties.put("authPreemptive", authPreemptive);

supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
supportingFiles.add(new SupportingFile("build.properties.mustache", "", "project/build.properties"));
supportingFiles.add(new SupportingFile("plugins.sbt.mustache", "", "project/plugins.sbt"));

importMapping.remove("List");
importMapping.remove("Set");
importMapping.remove("Map");

importMapping.put("DateTime", "org.joda.time.DateTime");
importMapping.put("ListBuffer", "scala.collection.mutable.ListBuffer");

typeMapping = new HashMap<String, String>();
typeMapping.put("Integer", "Int");
typeMapping.put("enum", "NSString");
typeMapping.put("array", "Seq");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("long", "Long");
typeMapping.put("float", "Float");
typeMapping.put("byte", "Byte");
typeMapping.put("short", "Short");
typeMapping.put("char", "Char");
typeMapping.put("long", "Long");
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
typeMapping.put("file", "File");

//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
typeMapping.put("ByteArray", "String");

instantiationTypes.put("array", "ListBuffer");
instantiationTypes.put("map", "HashMap");

cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING,
CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
}

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

if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming(
(String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
}

public void setModelPropertyNaming(String naming) {
if ("original".equals(naming) || "camelCase".equals(naming) ||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
this.modelPropertyNaming = naming;
} else {
throw new IllegalArgumentException("Invalid model property naming '" +
naming + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}

public String getModelPropertyNaming() {
return this.modelPropertyNaming;
}

@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(
name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a copy/paste. Can it be updated/fixed here, or does that affect something elsewhere?

String modifiedName = name;

Then, use modifiedName within the method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jim, you are right it is a copy paste from ScalaClientCodegen.Java. I guess this is needed for scala variables. Not sure what will break. Hence retained the logic.
With reference to method signatures.
Please have a look at https://github.com/lagom/sbt-lagom-descriptor-generator
The method signature generated by this PR matches with the one generated in above project.
Please let me know if you find any gaps.


if ("_".equals(name)) {
name = "_u";
}

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

name = getNameUsingModelPropertyNaming(name);

// for reserved word or word starting with number, append _
if (isReservedWord(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);
}

private String getNameUsingModelPropertyNaming(String name) {
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
case original:
return name;
case camelCase:
return camelize(name, true);
case PascalCase:
return camelize(name);
case snake_case:
return underscore(name);
default:
throw new IllegalArgumentException("Invalid model property naming '" +
name + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}

}

@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}

@Override
public String getName() {
return "scala-lagomApi";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change this to scala-lagom to conform to our naming convention.

}

@Override
public String getHelp() {
return "Generates a Lagom API in scala";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add the word "beta" to the description.

}

@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}

// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}

return camelize(operationId, true);
}

@Override
public String toModelName(final String name) {
final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix);

// camelize the model name
// phone_number => PhoneNumber
final String camelizedName = camelize(sanitizedName);

// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
final String modelName = "Model" + camelizedName;
LOGGER.warn(
camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}

// model name starts with number
if (name.matches("^\\d.*")) {
final String modelName =
"Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(
name + " (model name starts with number) cannot be used as model name. Renamed to "
+ modelName);
return modelName;
}

return camelizedName;
}

@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}

@Override
public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
objs = super.postProcessModelsEnum(objs);
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");

for (CodegenProperty var : cm.vars) {
if (var.isEnum) {
List<Object> enumValues = (List<Object>) var.allowableValues.get("values");

for (final ListIterator<Object> i = enumValues.listIterator(); i.hasNext(); ) {
final String element = String.valueOf(i.next());
i.set(element.replaceAll("^\"|\"$", ""));
}
}
}
}

//Needed import for Gson based libraries
if (additionalProperties.containsKey("gson")) {
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");

for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
// for enum model
if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) {
cm.imports.add(importMapping.get("SerializedName"));
Map<String, String> item = new HashMap<String, String>();
item.put("import", importMapping.get("SerializedName"));
imports.add(item);
}
}
}

return objs;
}

@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
ArrayList<CodegenOperation> oplist = (ArrayList<CodegenOperation>) operations.get("operation");

for (CodegenOperation codegenOperation : oplist) {
String path = codegenOperation.path;
codegenOperation.path = path.replaceAll("\\{", ":").replaceAll("}", "");
}
return objs;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ io.swagger.codegen.languages.RubyClientCodegen
io.swagger.codegen.languages.RustClientCodegen
io.swagger.codegen.languages.RustServerCodegen
io.swagger.codegen.languages.ScalaClientCodegen
io.swagger.codegen.languages.ScalaLagomServerCodegen
io.swagger.codegen.languages.ScalatraServerCodegen
io.swagger.codegen.languages.ScalazClientCodegen
io.swagger.codegen.languages.SilexServerCodegen
Expand All @@ -80,4 +81,4 @@ io.swagger.codegen.languages.TypeScriptFetchClientCodegen
io.swagger.codegen.languages.TypeScriptJqueryClientCodegen
io.swagger.codegen.languages.TypeScriptNodeClientCodegen
io.swagger.codegen.languages.UndertowCodegen
io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen
io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Swagger generated scala-lagomApi

## Overview
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the
[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This
is an example of building a swagger-enabled lagon-api.

This example uses the [lagomframework](https://www.lagomframework.com) lagomframework.

# Features which are not supported
- Form Parameters
- Seq in query parameters
- File Handling
Loading