org.openapitools.codegen.languages.N4jsClientCodegen Maven / Gradle / Ivy
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* 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
*
* https://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.openapitools.codegen.languages;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX_DESC;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE_DESC;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE_DESC;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenSecurity;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.IJsonSchemaValidationProperties;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
public class N4jsClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CHECK_REQUIRED_PARAMS_NOT_NULL = "checkRequiredParamsNotNull";
public static final String CHECK_SUPERFLUOUS_BODY_PROPS = "checkSuperfluousBodyProps";
public static final String GENERATE_DEFAULT_API_EXECUTER = "generateDefaultApiExecuter";
final Logger LOGGER = LoggerFactory.getLogger(N4jsClientCodegen.class);
final Set forbiddenChars = new HashSet<>();
private boolean checkRequiredBodyPropsNotNull = true;
private boolean checkSuperfluousBodyProps = true;
private boolean generateDefaultApiExecuter = true;
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String getName() {
return "n4js";
}
@Override
public String getHelp() {
return "Generates a n4js client.";
}
public N4jsClientCodegen() {
super();
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
specialCharReplacements.clear();
outputFolder = "generated-code" + File.separator + "n4js";
modelTemplateFiles.put("model.mustache", ".n4jsd");
apiTemplateFiles.put("api.mustache", ".n4js");
embeddedTemplateDir = templateDir = "n4js";
apiPackage = "";
modelPackage = "";
typeMapping = new HashMap();
typeMapping.put("Set", "Set");
typeMapping.put("set", "Set");
typeMapping.put("Array", "Array");
typeMapping.put("array", "Array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("char", "string");
typeMapping.put("float", "number");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("int", "int");
typeMapping.put("integer", "int");
typeMapping.put("number", "number");
typeMapping.put("double", "number");
typeMapping.put("object", "object");
typeMapping.put("Map", "any");
typeMapping.put("map", "any");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "string");
typeMapping.put("binary", "any");
typeMapping.put("File", "any");
typeMapping.put("file", "any");
typeMapping.put("ByteArray", "string");
typeMapping.put("UUID", "string");
typeMapping.put("URI", "string");
typeMapping.put("Error", "Error");
typeMapping.put("AnyType", "any");
importMapping.clear(); // not used
supportsInheritance = true;
supportsMultipleInheritance = false;
reservedWords.addAll(Arrays.asList(
// local variable names used in API methods (endpoints)
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions",
// N4JS reserved words
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue",
"debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final",
"finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int",
"interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true",
"try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<>(Arrays.asList("string", "String", "boolean", "number", "int",
"Object", "object", "Array", "any", "any+", "Error"));
defaultIncludes.add("~Object+");
defaultIncludes.add("Object+");
forbiddenChars.add("@");
cliOptions.clear();
cliOptions.add(new CliOption(API_PACKAGE, API_PACKAGE_DESC));
cliOptions.add(new CliOption(MODEL_PACKAGE, MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(API_NAME_PREFIX, API_NAME_PREFIX_DESC));
cliOptions.add(new CliOption(CHECK_REQUIRED_PARAMS_NOT_NULL,
"Iff true null-checks are performed for required parameters."));
cliOptions.add(new CliOption(CHECK_SUPERFLUOUS_BODY_PROPS,
"Iff true a new copy of the given body object is transmitted. This copy only contains those properties defined in its model specification."));
cliOptions.add(new CliOption(GENERATE_DEFAULT_API_EXECUTER,
"Iff true a default implementation of the api executer interface is generated."));
}
@Override
public void processOpts() {
super.processOpts();
// disable since otherwise Modules/Classes are not generated iff used as
// parameters only
GlobalSettings.setProperty("skipFormModel", "false");
supportingFiles.clear();
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiHelper.mustache", apiPackage, "ApiHelper.n4js"));
checkRequiredBodyPropsNotNull = processBooleanOpt(CHECK_REQUIRED_PARAMS_NOT_NULL,
checkRequiredBodyPropsNotNull);
checkSuperfluousBodyProps = processBooleanOpt(CHECK_SUPERFLUOUS_BODY_PROPS, checkSuperfluousBodyProps);
generateDefaultApiExecuter = processBooleanOpt(GENERATE_DEFAULT_API_EXECUTER, generateDefaultApiExecuter);
if (additionalProperties.get(API_PACKAGE) instanceof String) {
apiPackage = additionalProperties.get(API_PACKAGE).toString();
} else {
additionalProperties.put(API_PACKAGE, apiPackage);
}
if (additionalProperties.get(MODEL_PACKAGE) instanceof String) {
modelPackage = additionalProperties.get(MODEL_PACKAGE).toString();
} else {
additionalProperties.put(MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.get(API_NAME_PREFIX) instanceof String) {
apiNamePrefix = additionalProperties.get(API_NAME_PREFIX).toString();
} else {
additionalProperties.put(API_NAME_PREFIX, apiNamePrefix);
}
}
private boolean processBooleanOpt(String OPT, boolean defaultValue) {
boolean passedValue = defaultValue;
if (additionalProperties.containsKey(OPT)) {
Object value = additionalProperties.get(OPT);
if (value instanceof Boolean) {
passedValue = (Boolean) value;
} else {
try {
passedValue = Boolean.parseBoolean(value.toString());
} catch (Exception e) {
// ignore
}
}
}
additionalProperties.put(OPT, passedValue);
return defaultValue;
}
@Override
public String toModelFilename(String name) {
if (typeMapping.containsKey(name) || defaultIncludes.contains(name)) {
return name;
}
return super.toModelFilename(name);
}
public boolean checkRequiredBodyPropsNotNull() {
return checkRequiredBodyPropsNotNull;
}
public boolean checkSuperfluousBodyProps() {
return checkSuperfluousBodyProps;
}
public boolean generateDefaultApiExecuter() {
return generateDefaultApiExecuter;
}
@Override
public boolean getUseInlineModelResolver() {
return false;
}
@Override
public void setOpenAPI(OpenAPI openAPI) {
super.setOpenAPI(openAPI);
typeAliases.put("object", "~Object+");
}
@Override
protected boolean isReservedWord(String word) {
// case sensitive matching
return reservedWords.contains(word);
}
@Override
public String toAnyOfName(List names, Schema composedSchema) {
List types = getTypesFromSchemas(composedSchema.getAnyOf());
return String.join(" | ", types);
}
@Override
public String toOneOfName(List names, Schema composedSchema) {
List types = getTypesFromSchemas(composedSchema.getOneOf());
return String.join(" | ", types);
}
@Override
public String toAllOfName(List names, Schema composedSchema) {
List types = getTypesFromSchemas(composedSchema.getAllOf());
return String.join(" & ", types);
}
/**
* Extracts the list of type names from a list of schemas. Excludes `AnyType` if
* there are other valid types extracted.
*
* @param schemas list of schemas
* @return list of types
*/
@SuppressWarnings("rawtypes")
protected List getTypesFromSchemas(List schemas) {
List filteredSchemas = schemas.size() > 1 ? schemas.stream()
.filter(schema -> !"AnyType".equals(super.getSchemaType(schema))).collect(Collectors.toList())
: schemas;
return filteredSchemas.stream().map(schema -> getTypeDeclaration(schema)).distinct()
.collect(Collectors.toList());
}
@Override
protected void addImports(Set importsToBeAddedTo, IJsonSchemaValidationProperties type) {
Set imports = type.getImports(importContainerType, importBaseType, generatorMetadata.getFeatureSet());
Set mappedImports = new HashSet<>();
for (String imp : imports) {
String mappedImp = imp;
if (typeMapping.containsKey(imp)) {
mappedImp = typeMapping.get(imp);
} else {
mappedImp = imp;
}
mappedImports.add(mappedImp);
}
addImports(importsToBeAddedTo, mappedImports);
}
@Override
protected void addImport(Set importsToBeAddedTo, String type) {
String[] parts = splitComposedType(type);
for (String s : parts) {
super.addImport(importsToBeAddedTo, s);
}
}
private String[] splitComposedType(String name) {
return name.replace(" ", "").split("[|&<>]");
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
objs = super.postProcessModels(objs);
for (ModelMap modelMap : objs.getModels()) {
CodegenModel cgModel = modelMap.getModel();
if (cgModel.unescapedDescription != null && !cgModel.unescapedDescription.contains("\n * ")) {
cgModel.description = escapeTextWhileAllowingNewLines(cgModel.unescapedDescription.trim()).replace("\n",
"\n * ");
}
}
postProcessModelsEnum(objs); // enable enums
return objs;
}
@Override
protected void addImportsForPropertyType(CodegenModel model, CodegenProperty property) {
if (model.getIsAnyType()) {
return; // disable (unused) imports created for properties of type aliases
}
super.addImportsForPropertyType(model, property);
}
@Override
public Map postProcessAllModels(Map objs) {
objs = super.postProcessAllModels(objs);
for (String modelName : objs.keySet()) {
ModelsMap modelsMap = objs.get(modelName);
// imports
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy