org.openapitools.codegen.languages.AbstractEiffelCodegen Maven / Gradle / Ivy
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* 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 com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.openapitools.codegen.utils.OnceLogger.once;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public abstract class AbstractEiffelCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractEiffelCodegen.class);
private final Set parentModels = new HashSet<>();
private final Multimap childrenByParent = ArrayListMultimap.create();
public AbstractEiffelCodegen() {
super();
hideGenerationTimestamp = Boolean.FALSE;
setReservedWordsLowerCase(Arrays.asList(
// language reserved words
"across", "agent", "alias", "all", "and", "as", "assign", "attribute", "check", "class", "convert",
"create", "Current", "debug", "deferred", "do", "else", "elseif", "end", "ensure", "expanded", "export",
"external", "False", "feature", "from", "frozen", "if", "implies", "inherit", "inspect", "invariant",
"like", "local", "loop", "not", "note", "obsolete", "old", "once", "only", "or", "Precursor",
"redefine", "rename", "require", "rescue", "Result", "retry", "select", "separate", "then", "True",
"TUPLE", "undefine", "until", "variant", "Void", "when", "xor"));
defaultIncludes = new HashSet(Arrays.asList("map", "array"));
languageSpecificPrimitives = new HashSet(
Arrays.asList("BOOLEAN", "INTEGER_8", "INTEGER_16", "INTEGER_32", "INTEGER_64", "NATURAL_8",
"NATURAL_16", "NATURAL_32", "NATURAL_64", "REAL_32", "REAL_64"));
instantiationTypes.clear();
typeMapping.clear();
typeMapping.put("integer", "INTEGER_32");
typeMapping.put("long", "INTEGER_64");
typeMapping.put("number", "REAL_32");
typeMapping.put("float", "REAL_32");
typeMapping.put("double", "REAL_64");
typeMapping.put("boolean", "BOOLEAN");
typeMapping.put("string", "STRING_32");
typeMapping.put("UUID", "UUID"); //
typeMapping.put("URI", "STRING"); //
typeMapping.put("date", "DATE");
typeMapping.put("DateTime", "DATE_TIME");
typeMapping.put("date-time", "DATE_TIME");
typeMapping.put("password", "STRING");
typeMapping.put("File", "FILE");
typeMapping.put("file", "FILE");
typeMapping.put("binary", "FILE");
typeMapping.put("ByteArray", "ARRAY [NATURAL_8]");
typeMapping.put("object", "ANY");
typeMapping.put("map", "STRING_TABLE");
typeMapping.put("array", "LIST");
typeMapping.put("list", "LIST");
instantiationTypes.put("array", "ARRAYED_LIST");
instantiationTypes.put("list", "ARRAYED_LIST");
instantiationTypes.put("map", "STRING_TABLE");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Eiffel Cluster name (convention: lowercase).")
.defaultValue("openapi"));
cliOptions
.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Eiffel package version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC).defaultValue(Boolean.TRUE.toString()));
}
@Override
public String escapeReservedWord(String name) {
// Can't start with an underscore, as our fields need to start with an
// UppercaseLetter so that Go treats them as public/visible.
// Options?
// - MyName
// - AName
// - TheName
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
if (name.matches("^\\d.*")) {// prepend var_
return "var_" + name;
}
return "var_" + name;
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = sanitizeName(name.replaceAll("-", "_"));
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// pet_id
// petId => pet_id
name = unCamelize(name);
if (name.startsWith("_")) {
name = "var" + name;
}
// for reserved word
if (isReservedWord(name)) {
name = escapeReservedWord(name);
}
// for reserved word or word starting with number, append
if (name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// params should be lowercase. E.g. "person: PERSON"
return toVarName(name).toLowerCase(Locale.ROOT);
}
@Override
public String toModelName(String name) {
// phone_number => PHONE_NUMBER
return toModelFilename(name).toUpperCase(Locale.ROOT);
}
@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 " + ("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after
// camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to "
+ ("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response
// (after camelize)
}
return underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be
// assigned. Also declare the
// methods parameters as 'final'.
// e.g. PetApi.go => pet_api.go
return underscore(name) + "_api";
}
@Override
public String toApiTestFilename(String name) {
return toApiName(name).toLowerCase(Locale.ROOT) + "_test";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "DEFAULT_API";
}
return name.toUpperCase(Locale.ROOT) + "_API";
}
/**
* Overrides postProcessParameter to add a vendor extension
* "x-exportParamName". This is useful when paramName starts with a
* lowercase letter, but we need that param to be exportable (starts with an
* Uppercase letter).
*
* @param parameter CodegenParameter object to be processed.
*/
@Override
public void postProcessParameter(CodegenParameter parameter) {
// Give the base class a chance to process
super.postProcessParameter(parameter);
char firstChar = parameter.paramName.charAt(0);
// TODO: 5.0: Remove the camelCased vendorExtension below and ensure templates use the newer property naming.
once(LOGGER).warn("4.3.0 has deprecated the use of vendor extensions which don't follow lower-kebab casing standards with x- prefix.");
if (Character.isUpperCase(firstChar)) {
// First char is already uppercase, just use paramName.
parameter.vendorExtensions.put("x-exportParamName", parameter.paramName); // TODO: 5.0 Remove
parameter.vendorExtensions.put("x-export-param-name", parameter.paramName);
}
// It's a lowercase first char, let's convert it to uppercase
StringBuilder sb = new StringBuilder(parameter.paramName);
sb.setCharAt(0, Character.toUpperCase(firstChar));
parameter.vendorExtensions.put("x-exportParamName", sb.toString()); // TODO: 5.0 Remove
parameter.vendorExtensions.put("x-export-param-name", sb.toString());
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if (!isNullOrEmpty(model.parent)) {
parentModels.add(model.parent);
if (!childrenByParent.containsEntry(model.parent, model)) {
childrenByParent.put(model.parent, model);
}
}
if (!isNullOrEmpty(model.parentSchema)) {
model.parentSchema = model.parentSchema.toLowerCase(Locale.ROOT);
}
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return "LIST [" + getTypeDeclaration(inner) + "]";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
}
// return super.getTypeDeclaration(p);
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String scheamType = getSchemaType(p);
if (typeMapping.containsKey(scheamType)) {
return typeMapping.get(scheamType);
}
if (typeMapping.containsValue(scheamType)) {
return scheamType;
}
if (languageSpecificPrimitives.contains(scheamType)) {
return scheamType;
}
return toModelName(scheamType);
}
@Override
public String getSchemaType(Schema p) {
String scheamType = super.getSchemaType(p);
String type = null;
if (typeMapping.containsKey(scheamType)) {
type = typeMapping.get(scheamType);
if (languageSpecificPrimitives.contains(type))
return (type);
} else
type = scheamType;
return type;
}
@Override
public String toOperationId(String operationId) {
String sanitizedOperationId = sanitizeName(operationId);
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(sanitizedOperationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to "
+ camelize("call_" + operationId));
sanitizedOperationId = "call_" + sanitizedOperationId;
}
// method name from updateSomething to update_Something.
sanitizedOperationId = unCamelize(sanitizedOperationId);
return toEiffelFeatureStyle(sanitizedOperationId);
}
@Override
public Map postProcessOperationsWithModels(Map objs, List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy