com.centurylink.mdw.cli.SwaggerCodegen Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mdw-common Show documentation
Show all versions of mdw-common Show documentation
MDW is a workflow framework specializing in microservice orchestration
/*
* Copyright (C) 2018 CenturyLink, Inc.
*
* Licensed 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 com.centurylink.mdw.cli;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
public class SwaggerCodegen extends io.limberest.api.codegen.SwaggerCodegen {
public static final String NAME = "mdw";
public static final String TRIM_API_PATHS = "trimApiPaths";
public static final String GENERATED_FLOW_BASE_PACKAGE = "generatedFlowBasePackage";
public static final String INPUT_API_PACKAGE = "inputApiPackage";
public SwaggerCodegen() {
super();
embeddedTemplateDir = "codegen";
// standard opts to be overridden by user options
outputFolder = ".";
apiPackage = "com.centurylink.api.service";
modelPackage = "com.centurylink.api.model";
cliOptions.add(CliOption
.newString(TRIM_API_PATHS, "Trim API paths and adjust package names accordingly")
.defaultValue(Boolean.TRUE.toString()));
additionalProperties.put(TRIM_API_PATHS, true);
cliOptions.add(CliOption.newString(GENERATED_FLOW_BASE_PACKAGE,
"Base package for generated microservice orchestration workflow processes"));
// relevant once we submit a PR to swagger-code to become an official
// java library
supportedLibraries.put(NAME, getHelp());
setLibrary(NAME);
CliOption library = new CliOption(CodegenConstants.LIBRARY,
"library template (sub-template) to use");
library.setDefault(NAME);
library.setEnum(supportedLibraries);
library.setDefault(NAME);
cliOptions.add(library);
}
@Override
public String getHelp() {
return "Generates MDW REST service assets and Jsonable model classes.";
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(TRIM_API_PATHS)) {
this.setTrimApiPaths(convertPropertyToBoolean(TRIM_API_PATHS));
}
if (trimApiPaths && !additionalProperties.containsKey(INPUT_API_PACKAGE)) {
apiPackage = "";
}
if (additionalProperties.containsKey(GENERATED_FLOW_BASE_PACKAGE)) {
this.setGeneratedFlowBasePackage(
additionalProperties.get(GENERATED_FLOW_BASE_PACKAGE).toString());
}
importMapping.put("Jsonable", "com.centurylink.mdw.model.Jsonable");
importMapping.put("JsonRestService", "com.centurylink.mdw.services.rest.JsonRestService");
importMapping.put("ServiceException",
"com.centurylink.mdw.common.service.ServiceException");
importMapping.put("Map", "java.util.Map");
importMapping.put("SwaggerValidator",
"com.centurylink.mdw.service.api.SwaggerModelValidator");
importMapping.put("ValidationException",
"io.limberest.validate.ValidationException");
importMapping.put("JsonList", "com.centurylink.mdw.model.JsonList");
}
@Override
public String toApiName(String name) {
if (trimApiPaths) {
String camelized = DefaultCodegen.camelize(name);
String apiName = "";
for (String seg : camelized.split("\\{")) {
if (seg.length() > 0)
apiName += Character.toUpperCase(seg.charAt(0));
if (seg.length() > 1)
apiName += seg.substring(1);
}
apiName = apiName.replaceAll("\\}", "");
if (modelNames.contains(apiName))
apiName += "Api"; // avoid collisions
return apiName;
}
else {
return super.toApiName(name);
}
}
private List modelNames = new ArrayList<>();
@Override
public CodegenModel fromModel(String name, Model model, Map allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (!modelNames.contains(name))
modelNames.add(name);
codegenModel.imports.add("JSONObject");
codegenModel.imports.add("Jsonable");
return codegenModel;
}
@Override
public String toApiFilename(String name) {
String filename;
String pkgName;
if (!apiPackage().isEmpty()) {
filename = toApiName(name);
pkgName = apiPackage();
}
else if (trimApiPaths) {
filename = trimmedPaths.get(name) + "/" + toApiName(name);
pkgName = apiPackage() + trimmedPaths.get(name).replace('/', '.').substring(1);
}
else {
filename = super.toApiFilename(name);
pkgName = apiPackage();
}
File file = new File(
getOutputDir() + "/" + apiPackage().replace('.', '/') + "/" + filename);
mkPackage(pkgName, file.getParentFile());
return filename;
}
@Override
public String toModelFilename(String name) {
String filename = super.toModelFilename(name);
File file = new File(
getOutputDir() + "/" + modelPackage().replace('.', '/') + "/" + filename);
mkPackage(modelPackage, file.getParentFile());
return filename;
}
/**
* We use this for API package in our templates when trimmedPaths is true.
*/
@Override
public String toApiImport(String name) {
if (!apiPackage().isEmpty())
return apiPackage();
else if (trimApiPaths)
return trimmedPaths.get(name).substring(1).replace('/', '.');
else
return super.toApiImport(name);
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation,
Map definitions, Swagger swagger) {
CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions,
swagger);
op.imports.add("Map");
op.imports.remove("Request");
op.imports.remove("Response");
if (validateRequest) {
op.imports.remove("Result");
}
if (generatedFlowBasePackage != null) {
ProcessNamer processNamer = new ProcessNamer(generatedFlowBasePackage, path);
String processName = processNamer.getPackage() + "/"
+ processNamer.getName(op.httpMethod);
op.vendorExtensions.put("generatedFlow", processName);
}
return op;
}
Map trimmedPaths;
Map trimmedNames;
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation,
CodegenOperation co, Map> operations) {
super.addOperationToGroup(tag, resourcePath, operation, co, operations);
if (trimApiPaths) {
if (trimmedPaths == null)
trimmedPaths = new LinkedHashMap<>();
if (trimmedNames == null)
trimmedNames = new LinkedHashMap<>();
Map> ops = new LinkedHashMap<>();
for (String path : operations.keySet()) {
String pkgPath = path;
String baseName = path;
String className = path;
int slashCurly = pkgPath.lastIndexOf("/{");
if (slashCurly > 0) {
pkgPath = pkgPath.substring(0, slashCurly);
className = path.substring(0, slashCurly)
+ camelize(path.substring(slashCurly + 2, path.lastIndexOf("}")));
}
int pkgSlash = pkgPath.lastIndexOf("/");
if (pkgSlash > 0) {
pkgPath = pkgPath.substring(0, pkgSlash);
baseName = path.substring(pkgPath.length());
}
trimmedPaths.put(baseName, pkgPath);
trimmedNames.put(baseName, className);
ops.put(baseName, operations.get(path));
}
operations.clear();
operations.putAll(ops);
}
for (String path : operations.keySet()) {
List ops = operations.get(path);
for (CodegenOperation op : ops) {
// set restfulness according to our rules
op.isRestfulCreate = op.httpMethod.equalsIgnoreCase("POST");
op.isRestfulUpdate = op.httpMethod.equalsIgnoreCase("PUT")
|| op.httpMethod.equalsIgnoreCase("PATCH");
op.isRestfulShow = op.httpMethod.equalsIgnoreCase("GET");
op.isRestfulDestroy = op.httpMethod.equalsIgnoreCase("DELETE");
// we use nickname for content param -- ugh (unable to override
// isRestfulUpdate behavior)
op.nickname = op.isRestfulCreate || op.isRestfulUpdate ? "hasBody" : null;
}
}
}
protected boolean trimApiPaths = true;
public void setTrimApiPaths(boolean trimApiPaths) {
this.trimApiPaths = trimApiPaths;
}
protected String generatedFlowBasePackage;
public void setGeneratedFlowBasePackage(String basePackage) {
this.generatedFlowBasePackage = basePackage;
}
/**
* Creates a package if it doesn't exist. Only works from 6.1.
*/
public void mkPackage(String pkgName, File dir) {
try {
File metaDir = new File(dir + "/.mdw");
if (!metaDir.exists() && !metaDir.mkdirs())
throw new IOException("Cannot create directory: " + metaDir.getAbsolutePath());
File pkgFile = new File(metaDir + "/package.yaml");
if (!pkgFile.exists()) {
JSONObject pkgJson = new JSONObject();
pkgJson.put("name", pkgName);
pkgJson.put("version", "1.0.01");
pkgJson.put("schemaVersion", "6.1");
Files.write(Paths.get(pkgFile.getPath()), pkgJson.toString(2).getBytes());
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}