All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.openapi.visitor.GeneratorUtils Maven / Gradle / Ivy

/*
 * Copyright 2017-2024 original authors
 *
 * 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 io.micronaut.openapi.visitor;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.ast.ClassElement;
import io.micronaut.inject.ast.Element;
import io.micronaut.inject.ast.EnumElement;
import io.micronaut.inject.ast.MethodElement;
import io.micronaut.inject.ast.TypedElement;
import io.micronaut.inject.visitor.VisitorContext;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import static io.micronaut.openapi.visitor.ConvertUtils.findJsonValueType;
import static io.micronaut.openapi.visitor.ElementUtils.isAnnotationPresent;
import static io.micronaut.openapi.visitor.ElementUtils.isDeprecated;
import static io.micronaut.openapi.visitor.GeneratorExt.DEPRECATED_MESSAGE;
import static io.micronaut.openapi.visitor.GeneratorExt.ENUM_DEPRECATED;
import static io.micronaut.openapi.visitor.GeneratorExt.ENUM_DESCRIPTIONS;
import static io.micronaut.openapi.visitor.GeneratorExt.ENUM_VAR_NAMES;
import static io.micronaut.openapi.visitor.GeneratorExt.FORMAT;
import static io.micronaut.openapi.visitor.GeneratorExt.TYPE;
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_DEPRECATED;
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_DESCRIPTION;
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_HIDDEN;
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_NAME;

/**
 * OpenAPI Generator utilities methods.
 *
 * @since 4.12.4
 */
@Internal
public final class GeneratorUtils {

    private GeneratorUtils() {
    }

    public static void addSchemaDeprecatedExtension(Element el, Schema schema, VisitorContext context) {
        if (!ConfigUtils.isGeneratorExtensionsEnabled(context) || schema == null || el == null) {
            return;
        }

        var extensions = schema.getExtensions() != null ? schema.getExtensions() : new HashMap();
        addDeprecatedMessage(el, extensions, context);
        if (schema.getExtensions() == null && !extensions.isEmpty()) {
            schema.setExtensions(extensions);
        }
    }

    public static void addParameterDeprecatedExtension(TypedElement el, Parameter parameter, VisitorContext context) {
        if (!ConfigUtils.isGeneratorExtensionsEnabled(context) || parameter == null || el == null) {
            return;
        }

        var extensions = parameter.getExtensions() != null ? parameter.getExtensions() : new HashMap();
        addDeprecatedMessage(el, extensions, context);
        if (parameter.getExtensions() == null && !extensions.isEmpty()) {
            parameter.setExtensions(extensions);
        }
    }

    public static void addOperationDeprecatedExtension(MethodElement el, Operation operation, VisitorContext context) {
        if (!ConfigUtils.isGeneratorExtensionsEnabled(context) || operation == null || el == null) {
            return;
        }

        var extensions = operation.getExtensions() != null ? operation.getExtensions() : new HashMap();
        addDeprecatedMessage(el, extensions, context);
        if (!extensions.containsKey(DEPRECATED_MESSAGE)) {
            addDeprecatedMessage(el.getOwningType(), extensions, context);
        }
        if (operation.getExtensions() == null && !extensions.isEmpty()) {
            operation.setExtensions(extensions);
        }
    }

    private static void addDeprecatedMessage(Element el, Map extensions, VisitorContext context) {
        if (extensions.containsKey(DEPRECATED_MESSAGE)) {
            return;
        }

        String deprecatedMessage = null;
        var deprecatedAnn = el.getAnnotation("kotlin.Deprecated");
        if (deprecatedAnn != null) {
            deprecatedMessage = deprecatedAnn.stringValue().orElse(deprecatedAnn.stringValue("message").orElse(null));
        }
        if (deprecatedMessage == null) {
            var javadoc = el.getDocumentation().orElse(null);
            var javadocDescription = Utils.getJavadocParser().parse(javadoc);
            if (javadocDescription != null) {
                deprecatedMessage = javadocDescription.getDeprecatedDescription();
            }
        }
        if (StringUtils.isNotEmpty(deprecatedMessage)) {
            extensions.put(DEPRECATED_MESSAGE, deprecatedMessage);
        }
    }

    public static void addValidationMessages(Element el, Schema schema, Map messages, VisitorContext context) {
        if (!ConfigUtils.isGeneratorExtensionsEnabled(context) || schema == null || el == null) {
            return;
        }

        var extensions = schema.getExtensions() != null ? schema.getExtensions() : new HashMap();
        for (var entry : messages.entrySet()) {
            if (!extensions.containsKey(entry.getKey())) {
                extensions.put(entry.getKey(), entry.getValue());
            }
        }
        if (schema.getExtensions() == null && !extensions.isEmpty()) {
            schema.setExtensions(extensions);
        }
    }

    public static void addEnumExtensions(EnumElement enumEl, Schema schema, VisitorContext context) {

        if (!ConfigUtils.isGeneratorExtensionsEnabled(context) || enumEl == null) {
            return;
        }

        var extensions = schema.getExtensions();
        if (extensions == null) {
            extensions = new HashMap<>();
            schema.setExtensions(extensions);
        }

        String xType = null;
        String xFormat = null;

        ClassElement fieldType = findJsonValueType(enumEl, context);
        if (fieldType != null) {
            if (fieldType.isPrimitive()) {
                xType = fieldType.getSimpleName();
            } else {
                xType = fieldType.getSimpleName();
                if (xType.equalsIgnoreCase("byte")) {
                    xType = null;
                    xFormat = "int8";
                } else if (xType.equalsIgnoreCase("short")) {
                    xType = null;
                    xFormat = "int16";
                } else if (xType.equalsIgnoreCase("int")
                    || xType.equalsIgnoreCase("integer")
                    || xType.equalsIgnoreCase("long")
                    || xType.equalsIgnoreCase("float")
                    || xType.equalsIgnoreCase("double")) {
                    xType = null;
                    // because boolean enums generated as Boolean type
                } else if (xType.equalsIgnoreCase("boolean")) {
                    xType = null;
                } else if (xType.equalsIgnoreCase("char") || xType.equalsIgnoreCase("character")) {
                    xType = "char";
                }
            }
        }

        if (xType != null && !extensions.containsKey(TYPE)) {
            extensions.put(TYPE, xType);
        }
        if (xFormat != null && !extensions.containsKey(FORMAT)) {
            extensions.put(FORMAT, xFormat);
        }

        var enumVarNameList = new ArrayList();
        var enumVarDocList = new ArrayList();
        var enumVarDeprecatedList = new ArrayList();

        for (var enumConstEl : enumEl.elements()) {

            var schemaAnn = enumConstEl.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class);
            boolean isHidden = schemaAnn != null && schemaAnn.booleanValue(PROP_HIDDEN).orElse(false);

            if (isHidden
                || isAnnotationPresent(enumConstEl, Hidden.class)
                || isAnnotationPresent(enumConstEl, JsonIgnore.class)) {
                continue;
            }

            String enumVarName = null;
            if (schemaAnn != null) {
                enumVarName = schemaAnn.stringValue(PROP_NAME).orElse(null);
            }
            if (enumVarName == null) {
                enumVarName = enumConstEl.getName();
            }
            enumVarNameList.add(enumVarName);

            String enumVarDoc = null;
            if (schemaAnn != null) {
                enumVarDoc = schemaAnn.stringValue(PROP_DESCRIPTION).orElse(null);
            }
            if (enumVarDoc == null) {
                var enumConstJavadoc = enumConstEl.getDocumentation().orElse(null);
                if (enumConstJavadoc != null) {
                    var javadocDesc = Utils.getJavadocParser().parse(enumConstJavadoc);
                    if (javadocDesc != null && StringUtils.isNotEmpty(javadocDesc.getMethodDescription())) {
                        enumVarDoc = javadocDesc.getMethodDescription();
                    }
                }
            }
            enumVarDocList.add(enumVarDoc != null ? enumVarDoc : StringUtils.EMPTY_STRING);

            Boolean isDeprecated = null;
            if (schemaAnn != null) {
                isDeprecated = schemaAnn.booleanValue(PROP_DEPRECATED).orElse(null);
            }
            if (isDeprecated == null) {
                isDeprecated = isDeprecated(enumConstEl);
            }
            if (isDeprecated) {
                enumVarDeprecatedList.add(enumVarName);
            }
        }

        // check if upper case values equals with enum var names
        var generatedEnumVarNames = new ArrayList(schema.getEnum().size());
        for (var enumVal : schema.getEnum()) {
            generatedEnumVarNames.add(enumVal.toString().toUpperCase());
        }

        if (!enumVarNameList.isEmpty() && !extensions.containsKey(ENUM_VAR_NAMES)
            && !generatedEnumVarNames.equals(enumVarNameList)) {
            extensions.put(ENUM_VAR_NAMES, enumVarNameList);
        }
        if (!enumVarDocList.isEmpty() && !extensions.containsKey(ENUM_DESCRIPTIONS)) {
            var foundNotEmpty = false;
            for (var enumVarDoc : enumVarDocList) {
                if (StringUtils.isNotEmpty(enumVarDoc)) {
                    foundNotEmpty = true;
                    break;
                }
            }
            if (foundNotEmpty) {
                extensions.put(ENUM_DESCRIPTIONS, enumVarDocList);
            }
        }
        if (!enumVarDeprecatedList.isEmpty() && !extensions.containsKey(ENUM_DEPRECATED)) {
            extensions.put(ENUM_DEPRECATED, enumVarDeprecatedList);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy