diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java index e5f25a2e4c..25f31e185b 100644 --- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java +++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java @@ -18,6 +18,7 @@ * @param arrayItemType the OpenAPI schema type for array items * @param format the data format which further specifies the schema type * @param schemaTypeRef the OpenAPI schema type reference (used when the schema type is not a primitive type) + * @param nullable whether the parameter accepts {@code null} as a value, as defined by the OpenAPI schema * @param constraintNameRef the constraint name reference (used when the parameter is a constraint weight or any other parameter * related to a constraint) */ @@ -30,6 +31,7 @@ public record ModelConfigParameter( SchemaType arrayItemType, DataFormat format, String schemaTypeRef, + boolean nullable, String constraintNameRef) { } diff --git a/service/quarkus/deployment/src/main/java/ai/timefold/solver/service/quarkus/deployment/TimefoldModelDescriptorProcessor.java b/service/quarkus/deployment/src/main/java/ai/timefold/solver/service/quarkus/deployment/TimefoldModelDescriptorProcessor.java index a25d2a0ae1..f10e685b11 100644 --- a/service/quarkus/deployment/src/main/java/ai/timefold/solver/service/quarkus/deployment/TimefoldModelDescriptorProcessor.java +++ b/service/quarkus/deployment/src/main/java/ai/timefold/solver/service/quarkus/deployment/TimefoldModelDescriptorProcessor.java @@ -1439,6 +1439,7 @@ private ModelConfigParameter resolveModelConfigParameter(FieldInfo fieldInfo) { String description = null; SchemaType type = null; DataFormat format = null; + boolean nullable = false; Optional schemaAnnotationOptional = getSchemaAnnotation(fieldInfo); if (schemaAnnotationOptional.isPresent()) { AnnotationInstance schemaAnnotation = schemaAnnotationOptional.get(); @@ -1450,6 +1451,8 @@ private ModelConfigParameter resolveModelConfigParameter(FieldInfo fieldInfo) { schemaTypeAnnotationValue != null ? SchemaType.valueOf(schemaTypeAnnotationValue.asString()) : null; AnnotationValue formatAnnotationValue = schemaAnnotation.value("format"); format = formatAnnotationValue != null ? DataFormat.fromString(formatAnnotationValue.asString()) : null; + AnnotationValue nullableAnnotationValue = schemaAnnotation.value("nullable"); + nullable = nullableAnnotationValue != null && nullableAnnotationValue.asBoolean(); } name = name != null ? name : fieldInfo.name(); @@ -1474,7 +1477,7 @@ private ModelConfigParameter resolveModelConfigParameter(FieldInfo fieldInfo) { } return new ModelConfigParameter(name, title, description, kind, type, arrayItemType, format, schemaTypeRef, - constraintRef); + nullable, constraintRef); } private DocumentationDescriptor processModelDocumentation() { diff --git a/service/quarkus/deployment/src/test/java/ai/timefold/solver/service/quarkus/deployment/ModelConfigDescriptorSchemaTest.java b/service/quarkus/deployment/src/test/java/ai/timefold/solver/service/quarkus/deployment/ModelConfigDescriptorSchemaTest.java index 01bc90ea82..634aaa3f42 100644 --- a/service/quarkus/deployment/src/test/java/ai/timefold/solver/service/quarkus/deployment/ModelConfigDescriptorSchemaTest.java +++ b/service/quarkus/deployment/src/test/java/ai/timefold/solver/service/quarkus/deployment/ModelConfigDescriptorSchemaTest.java @@ -71,6 +71,7 @@ void detectModelConfigOverrides() throws IOException { softly.assertThat(primitive.format()).isEqualTo(DataFormat.Percentage); softly.assertThat(primitive.kind()).isEqualTo(ParameterKind.PARAMETER); softly.assertThat(primitive.type()).isEqualTo(Schema.SchemaType.INTEGER); + softly.assertThat(primitive.nullable()).isFalse(); ModelConfigParameter primitiveArray = modelConfigDescriptor.configParameters().get(2); softly.assertThat(primitiveArray.id()).isEqualTo("primitiveArrayParam"); @@ -97,6 +98,7 @@ void detectModelConfigOverrides() throws IOException { softly.assertThat(string.kind()).isEqualTo(ParameterKind.PARAMETER); softly.assertThat(string.type()).isEqualTo(Schema.SchemaType.STRING); softly.assertThat(string.schemaTypeRef()).isNull(); + softly.assertThat(string.nullable()).isTrue(); }); } }