Java tutorial
/* * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.ballerinalang.swagger.code.generator; import io.swagger.codegen.CliOption; import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenType; import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.SupportingFile; import io.swagger.models.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; /** * This the ballerina connector generator class. Here we can add/update templates to generate * different connectors, types services etc. */ public class BallerinaConnectorCodeGenerator extends DefaultCodegen implements CodegenConfig { private static final Logger LOGGER = LoggerFactory.getLogger(BallerinaConnectorCodeGenerator.class); protected String apiVersion = "1.0.0"; protected String apiPath = ""; public BallerinaConnectorCodeGenerator() { super(); // set the output folder here outputFolder = "generated-code/ballerina-connector"; /* * Models. You can write model files using the modelTemplateFiles map. * if you want to create one template for file, you can do so here. * for multiple files for model, just put another entry in the `modelTemplateFiles` with * a different extension */ modelTemplateFiles.clear(); /* * Api classes. You can write classes for each Api file with the apiTemplateFiles map. * as with models, add multiple entries with different extensions for multiple files per * class */ apiTemplateFiles.put("controller.mustache", // the template to use ".bal"); // the extension for each file to write /* * Template Location. This is the location which templates will be read from. The generator * will use the resource stream to attempt to read the templates. */ embeddedTemplateDir = templateDir = "ballerina-connector"; /* * Reserved words. Override this with reserved words specific to your language */ setReservedWordsLowerCase(Arrays.asList("action", "all", "any", "as", "boolean", "break", "catch", "connector", "const", "datatable", "double", "else", "exception", "fork", "function", "if", "import", "int", "json", "map", "message", "native", "package", "reply", "resource", "return", "service", "string", "struct", "throws", "timeout", "try", "typemapper", "while", "worker", "xml", "join")); defaultIncludes = new HashSet<String>(Arrays.asList("map", "array")); languageSpecificPrimitives = new HashSet<String>( Arrays.asList("string", "boolean", "int", "double", "map", "array")); instantiationTypes.clear(); instantiationTypes.put("array", "string[]"); instantiationTypes.put("map", "map"); typeMapping.clear(); typeMapping.put("integer", "int"); typeMapping.put("long", "long"); typeMapping.put("number", "float"); typeMapping.put("float", "float"); typeMapping.put("double", "double"); typeMapping.put("boolean", "boolean"); typeMapping.put("string", "string"); typeMapping.put("date", "string"); typeMapping.put("DateTime", "long"); typeMapping.put("password", "string"); typeMapping.put("binary", "string"); typeMapping.put("ByteArray", "string"); typeMapping.put("array", "string[]"); importMapping = new HashMap<String, String>(); cliOptions.clear(); cliOptions .add(new CliOption(CodegenConstants.PACKAGE_NAME, "Ballerina package name (convention: lowercase).") .defaultValue("swagger")); /* * Additional Properties. These values can be passed to the templates and * are available in models, apis, and supporting files */ additionalProperties.put("apiVersion", apiVersion); additionalProperties.put("apiPath", apiPath); /* * Supporting Files. You can write single files for the generator with the * entire object tree available. If the input file has a suffix of `.mustache * it will be processed by the template engine. Otherwise, it will be copied */ //supportingFiles.add(new SupportingFile("model.mustache", apiPath, "types.bal")); supportingFiles.add(new SupportingFile("json-model.mustache", apiPath, "types.json")); writeOptional(outputFolder, new SupportingFile("README.mustache", apiPath, "README.md")); writeOptional(outputFolder, new SupportingFile("json-model.mustache", apiPath, "types.json")); } @Override public String apiPackage() { return apiPath; } /** * Configures the type of generator. * * @return the CodegenType for this generator * @see io.swagger.codegen.CodegenType */ @Override public CodegenType getTag() { return CodegenType.SERVER; } /** * Configures a friendly name for the generator. This will be used by the generator * to select the library with the -l flag. * * @return the friendly name for the generator */ @Override public String getName() { return "ballerina-connector"; } /** * Returns human-friendly help for the generator. Provide the consumer with help * tips, parameters here * * @return A string value for the help message */ @Override public String getHelp() { return "Generates a Go server library using the swagger-tools project. By default, " + "it will also generate service classes--which you can disable with the `-Dnoservice` environment variable."; } @Override public String toApiName(String name) { if (name.length() == 0) { return "DefaultController"; } return initialCaps(name); } /** * Escapes a reserved word as defined in the `reservedWords` array. Handle escaping * those terms here. This logic is only called if a variable matches the reseved words * * @return the escaped term */ //@Override /*public String escapeReservedWord(String name) { if (this.reservedWordsMappings().containsKey(name)) { return this.reservedWordsMappings().get(name); } return "_" + name; }*/ @Override public Map<String, Object> postProcessOperations(Map<String, Object> objs) { super.postProcessOperations(objs); if (objs != null) { Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); if (operations != null) { List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); for (CodegenOperation operation : ops) { operation.httpMethod = operation.httpMethod.toLowerCase(); } } } return objs; } /** * Location to write api files. You can use the apiPackage() as defined when the class is * instantiated */ @Override public String apiFileFolder() { return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar); } @Override public String toModelName(String name) { return camelize(toModelFilename(name)); } @Override public String toOperationId(String operationId) { // method name cannot use reserved keyword, e.g. return if (isReservedWord(operationId)) { LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId))); operationId = "call_" + operationId; } String name = camelize(operationId); return Character.toLowerCase(name.charAt(0)) + name.substring(1); } @Override public String toModelFilename(String name) { if (!StringUtils.isEmpty(modelNamePrefix)) { name = modelNamePrefix + "_" + name; } if (!StringUtils.isEmpty(modelNameSuffix)) { name = name + "_" + modelNameSuffix; } name = sanitizeName(name); // model name cannot use reserved keyword, e.g. return if (isReservedWord(name)) { LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name)); name = "model_" + name; } return underscore(name); } /* @Override public String toApiFilename(String name) { name = name.replaceAll("-", "_"); return underscore(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 protected String getOrGenerateOperationId(Operation operation, String path, String httpMethod) { String operationId = operation.getOperationId(); if (path.contains("?")) { path = path.substring(0, path.indexOf("?")); } if (StringUtils.isBlank(operationId)) { String tmpPath = path.replaceAll("\\{", ""); tmpPath = tmpPath.replaceAll("\\}", ""); String[] parts = (tmpPath + "/" + httpMethod).split("/"); StringBuilder builder = new StringBuilder(); if ("/".equals(tmpPath)) { builder.append("root"); } for (int i = 0; i < parts.length; ++i) { String part = parts[i]; if (part.length() > 0) { if (builder.toString().length() == 0) { part = Character.toLowerCase(part.charAt(0)) + part.substring(1); } else { part = this.initialCaps(part); } builder.append(part); } } operationId = this.sanitizeName(builder.toString()); LOGGER.warn("Empty operationId found for path: " + httpMethod + " " + path + ". Renamed to auto-generated operationId: " + operationId); } return operationId; } }