diff --git a/framework/fel/java/maven-plugins/tool-maven-plugin/src/main/java/modelengine/fel/maven/complie/parser/ByteBuddySchemaParser.java b/framework/fel/java/maven-plugins/tool-maven-plugin/src/main/java/modelengine/fel/maven/complie/parser/ByteBuddySchemaParser.java index 9faafafcf..f388f499d 100644 --- a/framework/fel/java/maven-plugins/tool-maven-plugin/src/main/java/modelengine/fel/maven/complie/parser/ByteBuddySchemaParser.java +++ b/framework/fel/java/maven-plugins/tool-maven-plugin/src/main/java/modelengine/fel/maven/complie/parser/ByteBuddySchemaParser.java @@ -14,6 +14,8 @@ import modelengine.fel.tool.info.entity.ReturnPropertyEntity; import modelengine.fel.tool.info.entity.SchemaEntity; import modelengine.fitframework.annotation.Property; +import modelengine.fitframework.annotation.util.PropertyHelper; +import modelengine.fitframework.util.StringUtils; import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.method.MethodDescription; @@ -21,7 +23,6 @@ import static modelengine.fitframework.inspection.Validation.notNull; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -79,7 +80,9 @@ private static Map getStringObjectMap(ReturnPropertyEntity retur if (returnPropertyEntity.getConvertor() != null) { returnProperty.put("convertor", returnPropertyEntity.getConvertor()); } - returnProperty.put("examples", returnPropertyEntity.getExamples()); + if (returnPropertyEntity.getExamples() != null) { + returnProperty.put("examples", returnPropertyEntity.getExamples()); + } return returnProperty; } @@ -113,8 +116,14 @@ private static PropertyEntity parseProperty(ParameterDescription parameterDescri Property property = paramAnnotation.load(); entity.setDescription(property.description()); entity.setNeed(property.required()); - entity.setDefaultValue(property.defaultValue()); - entity.setExamples(Collections.singletonList(property.example())); + String defaultValue = property.defaultValue(); + if (defaultValue != null && PropertyHelper.isCustomValue(defaultValue)) { + entity.setDefaultValue(defaultValue); + } + String example = property.example(); + if (StringUtils.isNotEmpty(example)) { + entity.setExamples(Collections.singletonList(example)); + } } return entity; } @@ -127,7 +136,10 @@ private static ReturnPropertyEntity parseReturnProperty(MethodDescription method Property property = returnAnnotation.load(); returnPropertyEntity.setName(property.name()); returnPropertyEntity.setDescription(property.description()); - returnPropertyEntity.setExamples(Collections.singletonList(property.example())); + String example = property.example(); + if (StringUtils.isNotEmpty(example)) { + returnPropertyEntity.setExamples(Collections.singletonList(example)); + } } notNull(methodDescription.getReturnType(), "The return type cannot be null."); JsonNode jsonNode = JacksonTypeParser.getParameterSchema(methodDescription.getReturnType()); diff --git a/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/java/modelengine/fel/maven/compile/parser/weather/Rain.java b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/java/modelengine/fel/maven/compile/parser/weather/Rain.java index eb3a728d8..36190c423 100644 --- a/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/java/modelengine/fel/maven/compile/parser/weather/Rain.java +++ b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/java/modelengine/fel/maven/compile/parser/weather/Rain.java @@ -32,8 +32,8 @@ public interface Rain { */ @ToolMethod(name = "rain_today", description = "该方法获取今天的下雨信息") @Genericable("genericable_weather_rain_today") - String today(@Property(description = "查询地点", required = true, example = "Hangzhou") String location, - @Property(description = "查询日期", required = true) Date date, + String today(@Property(description = "查询地点", required = true, defaultValue = "Shanghai", example = "Hangzhou") + String location, @Property(description = "查询日期", required = true) Date date, @Property(description = "下雨的经纬度") RainPosition rainPosition, @Property(description = "其他信息") Object info); diff --git a/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json index 25b242a8a..39c094c7e 100644 --- a/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json +++ b/framework/fel/java/maven-plugins/tool-maven-plugin/src/test/resources/weather-tools.json @@ -17,14 +17,12 @@ "name" : "location", "type" : "string", "examples" : [ "Hangzhou" ], - "default" : "" + "default" : "Shanghai" }, "date" : { "description" : "查询日期", "name" : "date", - "type" : "string", - "examples" : [ "" ], - "default" : "" + "type" : "string" }, "rainPosition" : { "description" : "下雨的经纬度", @@ -38,17 +36,13 @@ "type" : "string" } }, - "examples" : [ "" ], - "required" : [ "latitude", "longitude" ], - "default" : "" + "required" : [ "latitude", "longitude" ] }, "info" : { "description" : "其他信息", "name" : "info", "type" : "object", - "properties" : { }, - "examples" : [ "" ], - "default" : "" + "properties" : { } } }, "required" : [ "location", "date" ] @@ -136,8 +130,7 @@ "name" : "", "description" : "获取今日下雨信息的结果", "type" : "string", - "convertor" : "", - "examples" : [ "" ] + "convertor" : "" } }, "runnables" : { @@ -174,8 +167,7 @@ "name" : "", "description" : "获取明日下雨信息的结果", "type" : "string", - "convertor" : "", - "examples" : [ "" ] + "convertor" : "" } }, "runnables" : { diff --git a/framework/fel/java/services/tool-service/src/main/java/modelengine/fel/tool/support/MethodToolMetadata.java b/framework/fel/java/services/tool-service/src/main/java/modelengine/fel/tool/support/MethodToolMetadata.java index 6b17f8caf..286b88e63 100644 --- a/framework/fel/java/services/tool-service/src/main/java/modelengine/fel/tool/support/MethodToolMetadata.java +++ b/framework/fel/java/services/tool-service/src/main/java/modelengine/fel/tool/support/MethodToolMetadata.java @@ -13,6 +13,7 @@ import modelengine.fel.tool.annotation.Group; import modelengine.fel.tool.annotation.ToolMethod; import modelengine.fitframework.annotation.Property; +import modelengine.fitframework.annotation.util.PropertyHelper; import modelengine.fitframework.json.schema.JsonSchemaManager; import modelengine.fitframework.util.MapBuilder; import modelengine.fitframework.util.StringUtils; @@ -67,7 +68,10 @@ public Object parameterDefaultValue(String name) { // TODO 需要考虑注解值的类型匹配与基础类型的默认值问题 Property annotation = parameter.getDeclaredAnnotation(Property.class); if (annotation != null) { - return annotation.defaultValue(); + String defaultValue = annotation.defaultValue(); + if (defaultValue != null && PropertyHelper.isCustomValue(defaultValue)) { + return defaultValue; + } } return null; }).orElse(null); diff --git a/framework/fel/java/services/tool-service/src/test/java/modelengine/fel/tool/support/MethodToolMetadataTest.java b/framework/fel/java/services/tool-service/src/test/java/modelengine/fel/tool/support/MethodToolMetadataTest.java index e6556901e..c3c339598 100644 --- a/framework/fel/java/services/tool-service/src/test/java/modelengine/fel/tool/support/MethodToolMetadataTest.java +++ b/framework/fel/java/services/tool-service/src/test/java/modelengine/fel/tool/support/MethodToolMetadataTest.java @@ -185,6 +185,13 @@ void shouldReturnParameterIndex() { assertThat(actual).isEqualTo(0); } + @Test + @DisplayName("当参数名称不存在时,返回 -1 序号") + void shouldReturnParameterIndexNegativeWhenNameNotExists() { + int actual = this.toolMetadata.parameterIndex("NotExists"); + assertThat(actual).isEqualTo(-1); + } + @Test @DisplayName("返回正确的必须参数名字列表") void shouldReturnRequired() { @@ -192,6 +199,15 @@ void shouldReturnRequired() { assertThat(parameterNames).containsExactly("P1"); } + @Test + @DisplayName("当参数为基础类型时,必须参数应包含该参数") + void shouldReturnRequiredWhenPrimitiveParam() throws NoSuchMethodException { + Method primitiveMethod = PrimitiveInterface.class.getDeclaredMethod("primitiveMethod", int.class); + Tool.Metadata primitiveMetadata = Tool.Metadata.fromMethod(primitiveMethod); + Set required = primitiveMetadata.requiredParameters(); + assertThat(required).containsExactly("i"); + } + @Test @DisplayName("返回正确的返回值类型") void shouldReturnReturnType() { @@ -199,6 +215,12 @@ void shouldReturnReturnType() { assertThat(type).isEqualTo(JsonSchemaManager.create().createSchema(String.class).toJsonObject()); } + @Test + @DisplayName("返回转换器字符串为空") + void shouldReturnEmptyReturnConverter() { + assertThat(this.toolMetadata.returnConverter()).isEqualTo(""); + } + @Test @DisplayName("返回正确的格式规范描述") void shouldReturnSchema() { @@ -217,6 +239,23 @@ void shouldReturnDefaultValueNull() { assertThat(definitionGroupName).isNotNull(); } + @Test + @DisplayName("参数默认值非自定义占位时应为 null") + void shouldReturnNullParameterDefaultValueWhenNotCustom() { + Object defaultValue = this.toolMetadata.parameterDefaultValue("P1"); + assertThat(defaultValue).isEqualTo("default_value"); + } + + @Test + @DisplayName("返回方法、名称、分组与描述信息正确") + void shouldReturnMethodAndDefinitions() { + assertThat(this.toolMetadata.getMethod()).isPresent(); + assertThat(this.toolMetadata.getMethod().orElse(null)).isEqualTo(this.testMethod); + assertThat(this.toolMetadata.definitionName()).isEqualTo("test_tool_def_name"); + assertThat(this.toolMetadata.definitionGroupName()).isEqualTo("test_def_group_name"); + assertThat(this.toolMetadata.description()).isEqualTo("测试方法的描述信息"); + } + @Group(name = "test_def_group_name") interface TestInterface { /** @@ -229,4 +268,10 @@ interface TestInterface { @Genericable(id = "t1", description = "desc") String testMethod(@Property(name = "P1", required = true, defaultValue = "default_value") String p1); } + + @Group(name = "primitive_group") + interface PrimitiveInterface { + @ToolMethod(name = "primitive_tool", description = "primitive") + int primitiveMethod(@Property(name = "i") int i); + } } diff --git a/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/Property.java b/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/Property.java index 83b38a36d..c8aedcd7d 100644 --- a/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/Property.java +++ b/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/Property.java @@ -24,6 +24,11 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) public @interface Property { + /** + * 表示未设置默认值的标记常量。 + */ + String UNSET_DEFAULT_VALUE = "$$Fit$UnsetDefaultValue$$"; + /** * 获取参数的名字。 * @@ -50,7 +55,7 @@ * * @return 表示参数的默认值的 {@link String}。 */ - String defaultValue() default StringUtils.EMPTY; + String defaultValue() default UNSET_DEFAULT_VALUE; /** * 获取参数的样例值。 diff --git a/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/util/PropertyHelper.java b/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/util/PropertyHelper.java new file mode 100644 index 000000000..c50bfafd5 --- /dev/null +++ b/framework/fit/java/fit-util/src/main/java/modelengine/fitframework/annotation/util/PropertyHelper.java @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved. + * This file is a part of the ModelEngine Project. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +package modelengine.fitframework.annotation.util; + +import modelengine.fitframework.annotation.Property; + +/** + * 为 Property 注解提供工具类。 + * + * @author 杭潇 + * @since 2025-10-29 + */ +public final class PropertyHelper { + /** + * 隐藏默认构造方法,避免工具类被实例化。 + */ + private PropertyHelper() {} + + /** + * 判断给定的默认值是否为设置状态。 + * + * @param defaultValue 要检查的默认值。 + * @return 如果自定义参数值则返回 {@code true},否则返回 {@code false}。 + */ + public static boolean isCustomValue(String defaultValue) { + return !Property.UNSET_DEFAULT_VALUE.equals(defaultValue); + } +} +