From 15bb50d822dfffd447bc512f79c42c188835540e Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 27 Mar 2018 15:24:10 +0800 Subject: [PATCH] add php silex generator --- .../codegen/languages/SilexServerCodegen.java | 246 ++++++++++++++++++ .../org.openapitools.codegen.CodegenConfig | 1 + .../codegen/silex/SilexServerOptionsTest.java | 33 +++ .../options/LumenServerOptionsProvider.java | 2 +- .../options/SilexServerOptionsProvider.java | 34 +++ 5 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SilexServerCodegen.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/silex/SilexServerOptionsTest.java create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/options/SilexServerOptionsProvider.java diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SilexServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SilexServerCodegen.java new file mode 100644 index 00000000000..aad5a466f01 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SilexServerCodegen.java @@ -0,0 +1,246 @@ +package org.openapitools.codegen.languages; + +import org.openapitools.codegen.CodegenConfig; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenType; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.DefaultCodegen; +import org.openapitools.codegen.SupportingFile; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.*; + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig { + protected String invokerPackage; + protected String groupId = "io.swagger"; + protected String artifactId = "swagger-server"; + protected String artifactVersion = "1.0.0"; + + public SilexServerCodegen() { + super(); + + invokerPackage = camelize("SwaggerServer"); + + String packagePath = "SwaggerServer"; + + modelPackage = packagePath + "/lib/models"; + apiPackage = packagePath + "/lib"; + outputFolder = "generated-code/php-silex"; + + // no model, api files + modelTemplateFiles.clear(); + apiTemplateFiles.clear(); + + embeddedTemplateDir = templateDir = "php-silex"; + + setReservedWordsLowerCase( + Arrays.asList( + "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") + ); + + additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + + // ref: http://php.net/manual/en/language.types.intro.php + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "boolean", + "int", + "integer", + "double", + "float", + "string", + "object", + "DateTime", + "mixed", + "number") + ); + + instantiationTypes.put("array", "array"); + instantiationTypes.put("map", "map"); + + // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types + typeMapping = new HashMap(); + typeMapping.put("integer", "int"); + typeMapping.put("long", "int"); + typeMapping.put("float", "float"); + typeMapping.put("double", "double"); + typeMapping.put("string", "string"); + typeMapping.put("byte", "int"); + typeMapping.put("boolean", "boolean"); + typeMapping.put("date", "DateTime"); + typeMapping.put("datetime", "DateTime"); + typeMapping.put("file", "string"); + typeMapping.put("map", "map"); + typeMapping.put("array", "array"); + typeMapping.put("list", "array"); + typeMapping.put("object", "object"); + //TODO binary should be mapped to byte array + // mapped to String as a workaround + typeMapping.put("binary", "string"); + + supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md")); + supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json")); + supportingFiles.add(new SupportingFile("index.mustache", packagePath.replace('/', File.separatorChar), "index.php")); + supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess")); + } + + @Override + public CodegenType getTag() { + return CodegenType.SERVER; + } + + @Override + public String getName() { + return "php-silex"; + } + + @Override + public String getHelp() { + return "Generates a PHP Silex server library."; + } + + @Override + public String escapeReservedWord(String name) { + if(this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); + } + + @Override + public String modelFileFolder() { + return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); + } + + @Override + public String getTypeDeclaration(Schema p) { + if (p instanceof ArraySchema) { + ArraySchema ap = (ArraySchema) p; + Schema inner = ap.getItems(); + return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; + } else if (p instanceof MapSchema) { + MapSchema mp = (MapSchema) p; + Schema inner = (Schema) mp.getAdditionalProperties(); + return getSchemaType(p) + "[string," + getTypeDeclaration(inner) + "]"; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSchemaType(Schema p) { + String swaggerType = super.getSchemaType(p); + String type = null; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type)) { + return type; + } else if (instantiationTypes.containsKey(type)) { + return type; + } + } else { + type = swaggerType; + } + if (type == null) { + return null; + } + return toModelName(type); + } + + @Override + public String toDefaultValue(Schema p) { + return "null"; + } + + + @Override + public String toVarName(String name) { + // return the name in underscore style + // PhoneNumber => phone_number + name = underscore(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + // parameter name starting with number won't compile + // need to escape it by appending _ at the beginning + if (name.matches("^\\d.*")) { + name = "_" + 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 + if (isReservedWord(name)) { + escapeReservedWord(name); // e.g. return => _return + } + + // 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 escapeQuotationMark(String input) { + // remove ' to avoid code injection + return input.replace("'", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + List operationList = (List) operations.get("operation"); + for (CodegenOperation op : operationList) { + String path = new String(op.path); + String[] items = path.split("/", -1); + String opsPath = ""; + int pathParamIndex = 0; + + for (int i = 0; i < items.length; ++i) { + if (items[i].matches("^\\{(.*)\\}$")) { // wrap in {} + // camelize path variable + items[i] = "{" + camelize(items[i].substring(1, items[i].length()-1), true) + "}"; + } + } + + op.path = StringUtils.join(items, "/"); + } + + return objs; + } + +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 63c901e2d6b..83da3ad5841 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -7,3 +7,4 @@ org.openapitools.codegen.languages.PythonClientCodegen org.openapitools.codegen.languages.Rails5ServerCodegen org.openapitools.codegen.languages.RubyClientCodegen org.openapitools.codegen.languages.SlimFrameworkServerCodegen +org.openapitools.codegen.languages.SilexServerCodegen diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/silex/SilexServerOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/silex/SilexServerOptionsTest.java new file mode 100644 index 00000000000..3f8ac24de59 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/silex/SilexServerOptionsTest.java @@ -0,0 +1,33 @@ +package org.openapitools.codegen.silex; + +import org.openapitools.codegen.AbstractOptionsTest; +import org.openapitools.codegen.CodegenConfig; +import org.openapitools.codegen.languages.SilexServerCodegen; +import org.openapitools.codegen.options.SilexServerOptionsProvider; + +import mockit.Expectations; +import mockit.Tested; + +public class SilexServerOptionsTest extends AbstractOptionsTest { + + @Tested + private SilexServerCodegen clientCodegen; + + public SilexServerOptionsTest() { + super(new SilexServerOptionsProvider()); + } + + @Override + protected CodegenConfig getCodegenConfig() { + return clientCodegen; + } + + @SuppressWarnings("unused") + @Override + protected void setExpectations() { + new Expectations(clientCodegen) {{ + clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(SilexServerOptionsProvider.SORT_PARAMS_VALUE)); + times = 1; + }}; + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/options/LumenServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/options/LumenServerOptionsProvider.java index 90c5b90a1c6..ad7e7d8fef5 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/options/LumenServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/options/LumenServerOptionsProvider.java @@ -24,7 +24,7 @@ public class LumenServerOptionsProvider implements OptionsProvider { @Override public String getLanguage() { - return "lumen"; + return "php-lumen"; } @Override diff --git a/modules/openapi-generator/src/test/java/org/openapitools/options/SilexServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/options/SilexServerOptionsProvider.java new file mode 100644 index 00000000000..de4a9202611 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/options/SilexServerOptionsProvider.java @@ -0,0 +1,34 @@ +package org.openapitools.codegen.options; + +import org.openapitools.codegen.CodegenConstants; + +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +public class SilexServerOptionsProvider implements OptionsProvider { + public static final String SORT_PARAMS_VALUE = "false"; + public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true"; + public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false"; + public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true"; + + @Override + public String getLanguage() { + return "php-silex"; + } + + @Override + public Map createOptions() { + ImmutableMap.Builder builder = new ImmutableMap.Builder(); + return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) + .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) + .put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE) + .build(); + } + + @Override + public boolean isServer() { + return true; + } +}