Skip to content

Commit

Permalink
Added schema duplication resolution mode
Browse files Browse the repository at this point in the history
  • Loading branch information
altro3 committed Aug 17, 2024
1 parent cbdbfe9 commit 413523c
Show file tree
Hide file tree
Showing 24 changed files with 363 additions and 230 deletions.
10 changes: 5 additions & 5 deletions openapi/openapi-custom-schema-for-class.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
micronaut.openapi.schema.io.micronaut.openapi.ObjectId=java.lang.String
micronaut.openapi.schema.io.micronaut.openapi.JAXBElement=io.micronaut.openapi.MyJaxbElement
micronaut.openapi.schema.io.micronaut.openapi.JAXBElement<test.XmlElement2>=io.micronaut.openapi.MyJaxbElement2
micronaut.openapi.schema.io.micronaut.openapi.JAXBElement<test.XmlElement3>=io.micronaut.openapi.MyJaxbElement3
micronaut.openapi.schema.io.micronaut.openapi.JAXBElement<test.XmlElement4>=io.micronaut.openapi.MyJaxbElement4
micronaut.openapi.schema.mapping.io.micronaut.openapi.ObjectId=java.lang.String
micronaut.openapi.schema.mapping.io.micronaut.openapi.JAXBElement=io.micronaut.openapi.MyJaxbElement
micronaut.openapi.schema.mapping.io.micronaut.openapi.JAXBElement<test.XmlElement2>=io.micronaut.openapi.MyJaxbElement2
micronaut.openapi.schema.mapping.io.micronaut.openapi.JAXBElement<test.XmlElement3>=io.micronaut.openapi.MyJaxbElement3
micronaut.openapi.schema.mapping.io.micronaut.openapi.JAXBElement<test.XmlElement4>=io.micronaut.openapi.MyJaxbElement4
Original file line number Diff line number Diff line change
@@ -1 +1 @@
micronaut.openapi.schema.io.micronaut.data.model.Page=io.micronaut.openapi.SwaggerPage
micronaut.openapi.schema.mapping.io.micronaut.data.model.Page=io.micronaut.openapi.SwaggerPage
4 changes: 2 additions & 2 deletions openapi/openapi-schema-decorators.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
micronaut.openapi.schema-postfix.io.micronaut.openapi.api.v1_0_0=1_0_0
micronaut.openapi.schema-postfix.io.micronaut.openapi.api.v2_0_1=2_0_1
micronaut.openapi.schema.mapping-postfix.io.micronaut.openapi.api.v1_0_0=1_0_0
micronaut.openapi.schema.mapping-postfix.io.micronaut.openapi.api.v2_0_1=2_0_1
38 changes: 27 additions & 11 deletions openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_ENABLED;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_ENVIRONMENTS;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_EXPAND_PREFIX;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_EXTRA_SCHEMA_ENABLED;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_GROUPS;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_PROJECT_DIR;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_DUPLICATE_RESOLUTION;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_MAPPING;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_INNER_CLASS;
Expand Down Expand Up @@ -195,7 +196,7 @@ public static ClassElement getCustomSchema(String className, Map<String, ClassEl
// third read environments properties
Environment environment = getEnv(context);
if (environment != null) {
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA, StringConvention.RAW).entrySet()) {
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_MAPPING, StringConvention.RAW).entrySet()) {
String configuredClassName = entry.getKey();
String targetClassName = (String) entry.getValue();
readCustomSchema(configuredClassName, targetClassName, customSchemas, context);
Expand Down Expand Up @@ -260,6 +261,14 @@ public static boolean isSchemaNameSeparatorEmpty(VisitorContext context) {
return value;
}

public static DuplicateResolution getSchemaDuplicateResolution(VisitorContext context) {
var value = getConfigProperty(MICRONAUT_OPENAPI_SCHEMA_DUPLICATE_RESOLUTION, context);
if (StringUtils.isNotEmpty(value) && DuplicateResolution.ERROR.name().equalsIgnoreCase(value)) {
return DuplicateResolution.ERROR;
}
return DuplicateResolution.AUTO;
}

public static String getGenericSeparator(VisitorContext context) {
if (isSchemaNameSeparatorEmpty(context)) {
return EMPTY_STRING;
Expand Down Expand Up @@ -299,7 +308,7 @@ public static boolean isExtraSchemasEnabled(VisitorContext context) {
if (loadedValue != null) {
return loadedValue;
}
boolean value = getBooleanProperty(MICRONAUT_OPENAPI_EXTRA_SCHEMA_ENABLED, true, context);
boolean value = getBooleanProperty(MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED, true, context);
ContextUtils.put(MICRONAUT_INTERNAL_EXTRA_SCHEMA_ENABLED, value, context);
return value;
}
Expand Down Expand Up @@ -581,7 +590,6 @@ public static Map<String, GroupProperties> getGroupsPropertiesMap(VisitorContext
* Returns the EndpointsConfiguration.
*
* @param context The context.
*
* @return The EndpointsConfiguration.
*/
public static EndpointsConfiguration endpointsConfiguration(VisitorContext context) {
Expand Down Expand Up @@ -709,10 +717,10 @@ private static void readSchemaDecorators(Properties props, Map<String, SchemaDec
private static void readCustomSchemas(Properties props, Map<String, CustomSchema> customSchemas, VisitorContext context) {

for (String prop : props.stringPropertyNames()) {
if (!prop.startsWith(MICRONAUT_OPENAPI_SCHEMA) || prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_PREFIX) || prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_POSTFIX)) {
if (!prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_MAPPING) || prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_PREFIX) || prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_POSTFIX)) {
continue;
}
String className = prop.substring(MICRONAUT_OPENAPI_SCHEMA.length() + 1);
String className = prop.substring(MICRONAUT_OPENAPI_SCHEMA_MAPPING.length() + 1);
String targetClassName = props.getProperty(prop);
readCustomSchema(className, targetClassName, customSchemas, context);
}
Expand Down Expand Up @@ -823,8 +831,8 @@ public static Properties readOpenApiConfigFile(VisitorContext context) {
}
var openApiProperties = new Properties();
String cfgFile = context != null
? ContextUtils.getOptions(context).getOrDefault(MICRONAUT_OPENAPI_CONFIG_FILE, System.getProperty(MICRONAUT_OPENAPI_CONFIG_FILE, OPENAPI_CONFIG_FILE))
: System.getProperty(MICRONAUT_OPENAPI_CONFIG_FILE, OPENAPI_CONFIG_FILE);
? ContextUtils.getOptions(context).getOrDefault(MICRONAUT_OPENAPI_CONFIG_FILE, System.getProperty(MICRONAUT_OPENAPI_CONFIG_FILE, OPENAPI_CONFIG_FILE))
: System.getProperty(MICRONAUT_OPENAPI_CONFIG_FILE, OPENAPI_CONFIG_FILE);
if (StringUtils.isNotEmpty(cfgFile)) {
Path cfg = resolve(context, Paths.get(cfgFile));
if (Files.isReadable(cfg)) {
Expand Down Expand Up @@ -945,8 +953,8 @@ private static boolean isEnvEnabled(VisitorContext context) {
* @param classElement class element
*/
record CustomSchema(
List<String> typeArgs,
ClassElement classElement
List<String> typeArgs,
ClassElement classElement
) {
}

Expand Down Expand Up @@ -974,4 +982,12 @@ public void setPostfix(String postfix) {
this.postfix = postfix;
}
}

/**
* Duplicate schema resolution mode
*/
public enum DuplicateResolution {
AUTO,
ERROR,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public interface ContextProperty {
*/
String MICRONAUT_INTERNAL_GENERATION_SPEC_ENABLED = "micronaut.internal.generation.spec.enabled";
/**
* Loaded micronaut.openapi.extra.schema.enabled value.
* Loaded micronaut.openapi.schema.extra.enabled value.
* <br>
* Default: true
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,6 @@ public interface OpenApiConfigProperty {
* Default: true
*/
String MICRONAUT_OPENAPI_ENABLED = "micronaut.openapi.enabled";
/**
* System property that enables or disables schema name separator for generics and inner classes.
* If it's true separators will be skipped. For example, schema name for class with name
* {@code MyClass.MyInnerClass<MyGeneric1, MyGeneric2>} will be
* {@code MyClassMyInnerClassMyGeneric1MyGeneric2}
* <br>
* Default: false
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY = "micronaut.openapi.schema.name.separator.empty";
/**
* System property to set custom separator for generic classes. By default, it is "_".
* <br>
* Default: _
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC = "micronaut.openapi.schema.name.separator.generic";
/**
* System property to set custom separator for inner classes. By default, it is ".".
* <br>
* Default: .
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_INNER_CLASS = "micronaut.openapi.schema.name.separator.inner-class";
/**
* System property that enables generating OpenAPI version 3.1.
* <br>
Expand All @@ -68,10 +47,6 @@ public interface OpenApiConfigProperty {
* System property that enables setting the open api config file.
*/
String MICRONAUT_OPENAPI_CONFIG_FILE = "micronaut.openapi.config.file";
/**
* System property that enables extra schema processing.
*/
String MICRONAUT_OPENAPI_EXTRA_SCHEMA_ENABLED = "micronaut.openapi.extra.schema.enabled";
/**
* Prefix for expandable properties.
*/
Expand Down Expand Up @@ -180,40 +155,79 @@ public interface OpenApiConfigProperty {
*/
String MICRONAUT_JACKSON_JSON_VIEW_ENABLED = "jackson.json-view.enabled";

/**
* System property that enables extra schema processing.
*/
String MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED = "micronaut.openapi.schema.extra.enabled";
/**
* System property to set schema duplicate resolution. Available values:
* - auto - micronaut-openapi automatically add index suffix to duplicate schema.
* - error - micronaut-openapi throws an exception when found duplicate schema.
* <br>
* Default: auto
*/
String MICRONAUT_OPENAPI_SCHEMA_DUPLICATE_RESOLUTION = "micronaut.openapi.schema.duplicate-resolution";
/**
* System property that enables or disables schema name separator for generics and inner classes.
* If it's true separators will be skipped. For example, schema name for class with name
* {@code MyClass.MyInnerClass<MyGeneric1, MyGeneric2>} will be
* {@code MyClassMyInnerClassMyGeneric1MyGeneric2}
* <br>
* Default: false
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY = "micronaut.openapi.schema.name.separator.empty";
/**
* System property to set custom separator for generic classes. By default, it is "_".
* <br>
* Default: _
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC = "micronaut.openapi.schema.name.separator.generic";
/**
* System property to set custom separator for inner classes. By default, it is ".".
* <br>
* Default: .
*/
String MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_INNER_CLASS = "micronaut.openapi.schema.name.separator.inner-class";

/**
* Properties prefix to set custom schema implementations for selected classes.
* For example, if you want to set simple 'java.lang.String' class to some complex 'org.somepackage.MyComplexType' class you need to write:
* <p>
* micronaut.openapi.schema.org.somepackage.MyComplexType=java.lang.String
* micronaut.openapi.schema.mapping.org.somepackage.MyComplexType=java.lang.String
* <p>
* Also, you can set it in your application.yml file like this:
* <p>
* <pre>
* micronaut:
* openapi:
* schema:
* org.somepackage.MyComplexType: java.lang.String
* org.somepackage.MyComplexType2: java.lang.Integer
* openapi:
* schema:
* mapping:
* org.somepackage.MyComplexType: java.lang.String
* org.somepackage.MyComplexType2: java.lang.Integer
* </pre>
* ...
*/
String MICRONAUT_OPENAPI_SCHEMA = "micronaut.openapi.schema";
String MICRONAUT_OPENAPI_SCHEMA_MAPPING = "micronaut.openapi.schema.mapping";
/**
* Properties prefix to set schema name prefix or postfix by package.
* For example, if you have some classes with same names in different packages you can set postfix like this:
* <p>
* micronaut.openapi.schema-postfix.org.api.v1_0_0=1_0_0
* micronaut.openapi.schema-postfix.org.api.v2_0_0=2_0_0
* micronaut.openapi.schema.mapping-postfix.org.api.v1_0_0=1_0_0
* micronaut.openapi.schema.mapping-postfix.org.api.v2_0_0=2_0_0
* <p>
* Also, you can set it in your application.yml file like this:
* <p>
* <pre>
* micronaut:
* openapi:
* schema-postfix:
* org.api.v1_0_0: 1_0_0
* org.api.v2_0_0: 2_0_0
* ...
* openapi:
* schema:
* mapping-postfix:
* org.api.v1_0_0: 1_0_0
* org.api.v2_0_0: 2_0_0
* </pre>
*/
String MICRONAUT_OPENAPI_SCHEMA_PREFIX = "micronaut.openapi.schema-prefix";
String MICRONAUT_OPENAPI_SCHEMA_POSTFIX = "micronaut.openapi.schema-postfix";
String MICRONAUT_OPENAPI_SCHEMA_PREFIX = "micronaut.openapi.schema.mapping-prefix";
String MICRONAUT_OPENAPI_SCHEMA_POSTFIX = "micronaut.openapi.schema.mapping-postfix";
/**
* Properties prefix to set custom schema implementations for selected classes.
* For example, if you want to set simple 'java.lang.String' class to some complex 'org.somepackage.MyComplexType' class you need to write:
Expand All @@ -222,15 +236,16 @@ public interface OpenApiConfigProperty {
* <p>
* Also, you can set it in your application.yml file like this:
* <p>
* <pre>
* micronaut:
* openapi:
* group:
* my-group1:
* title: Title 1
* filename: swagger-${group}-${apiVersion}-${version}.yml
* my-group2:
* title: Title 2
* ...
* openapi:
* group:
* my-group1:
* title: Title 1
* filename: swagger-${group}-${apiVersion}-${version}.yml
* my-group2:
* title: Title 2
* </pre>
*/
String MICRONAUT_OPENAPI_GROUPS = "micronaut.openapi.groups";

Expand Down Expand Up @@ -275,31 +290,31 @@ public interface OpenApiConfigProperty {
* All supported annotation processor properties.
*/
Set<String> ALL = Set.of(
MICRONAUT_OPENAPI_ENABLED,
MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH,
MICRONAUT_OPENAPI_PROPERTY_NAMING_STRATEGY,
MICRONAUT_OPENAPI_VIEWS_SPEC,
MICRONAUT_OPENAPI_FILENAME,
MICRONAUT_OPENAPI_JSON_FORMAT,
MICRONAUT_OPENAPI_ENVIRONMENTS,
MICRONAUT_ENVIRONMENT_ENABLED,
MICRONAUT_OPENAPI_FIELD_VISIBILITY_LEVEL,
MICRONAUT_CONFIG_FILE_LOCATIONS,
MICRONAUT_OPENAPI_TARGET_FILE,
MICRONAUT_OPENAPI_VIEWS_DEST_DIR,
MICRONAUT_OPENAPI_ADDITIONAL_FILES,
MICRONAUT_OPENAPI_CONFIG_FILE,
MICRONAUT_OPENAPI_SECURITY_ENABLED,
MICRONAUT_OPENAPI_VERSIONING_ENABLED,
MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION,
MICRONAUT_OPENAPI_PROJECT_DIR,
MICRONAUT_OPENAPI_ADOC_ENABLED,
MICRONAUT_OPENAPI_ADOC_TEMPLATES_DIR_PATH,
MICRONAUT_OPENAPI_ADOC_TEMPLATE_FILENAME,
MICRONAUT_OPENAPI_ADOC_OUTPUT_DIR_PATH,
MICRONAUT_OPENAPI_ADOC_OUTPUT_FILENAME,
MICRONAUT_OPENAPI_ADOC_OPENAPI_PATH,
MICRONAUT_OPENAPI_SWAGGER_FILE_GENERATION_ENABLED,
MICRONAUT_OPENAPI_EXTRA_SCHEMA_ENABLED
MICRONAUT_OPENAPI_ENABLED,
MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH,
MICRONAUT_OPENAPI_PROPERTY_NAMING_STRATEGY,
MICRONAUT_OPENAPI_VIEWS_SPEC,
MICRONAUT_OPENAPI_FILENAME,
MICRONAUT_OPENAPI_JSON_FORMAT,
MICRONAUT_OPENAPI_ENVIRONMENTS,
MICRONAUT_ENVIRONMENT_ENABLED,
MICRONAUT_OPENAPI_FIELD_VISIBILITY_LEVEL,
MICRONAUT_CONFIG_FILE_LOCATIONS,
MICRONAUT_OPENAPI_TARGET_FILE,
MICRONAUT_OPENAPI_VIEWS_DEST_DIR,
MICRONAUT_OPENAPI_ADDITIONAL_FILES,
MICRONAUT_OPENAPI_CONFIG_FILE,
MICRONAUT_OPENAPI_SECURITY_ENABLED,
MICRONAUT_OPENAPI_VERSIONING_ENABLED,
MICRONAUT_OPENAPI_JSON_VIEW_DEFAULT_INCLUSION,
MICRONAUT_OPENAPI_PROJECT_DIR,
MICRONAUT_OPENAPI_ADOC_ENABLED,
MICRONAUT_OPENAPI_ADOC_TEMPLATES_DIR_PATH,
MICRONAUT_OPENAPI_ADOC_TEMPLATE_FILENAME,
MICRONAUT_OPENAPI_ADOC_OUTPUT_DIR_PATH,
MICRONAUT_OPENAPI_ADOC_OUTPUT_FILENAME,
MICRONAUT_OPENAPI_ADOC_OPENAPI_PATH,
MICRONAUT_OPENAPI_SWAGGER_FILE_GENERATION_ENABLED,
MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ private void processExtraSchemaClass(ClassElement classEl, VisitorContext contex
if (classEl == null) {
return;
}
String schemaName = stringValue(classEl, io.swagger.v3.oas.annotations.media.Schema.class, PROP_NAME)
.orElse(computeDefaultSchemaName(null, classEl, classEl.getTypeArguments(), context, null));
String schemaName = computeDefaultSchemaName(stringValue(classEl, io.swagger.v3.oas.annotations.media.Schema.class, PROP_NAME).orElse(null),
null, classEl, classEl.getTypeArguments(), context, null);
var schema = getSchemaDefinition(resolveOpenApi(context), context, classEl, classEl.getTypeArguments(), null, Collections.emptyList(), null);
if (schema == null) {
return;
Expand Down
Loading

0 comments on commit 413523c

Please sign in to comment.