Skip to content

Commit 1fbbfe6

Browse files
Cherished-lcherish_li
andauthored
[fit] 修复校验泛型元素为空时的错误 (#7)
* [fit] 修复校验泛型元素为空时的错误 * [fit] 修改版权 * [fit] 修改检视意见:测试校验注解One -> MinSize * [fit] 测试校验注解修改为集合最大值上限 --------- Co-authored-by: cherish_li <cherish_li@noreply.gitcode.com>
1 parent e84a7f3 commit 1fbbfe6

File tree

5 files changed

+161
-3
lines changed

5 files changed

+161
-3
lines changed

framework/fit/java/fit-extension/fit-validation/src/main/java/modelengine/fitframework/validation/ValidationHandler.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import modelengine.fitframework.util.AnnotationUtils;
1717
import modelengine.fitframework.util.ArrayUtils;
1818
import modelengine.fitframework.util.CollectionUtils;
19+
import modelengine.fitframework.util.MapUtils;
1920
import modelengine.fitframework.util.ObjectUtils;
2021
import modelengine.fitframework.util.ReflectionUtils;
2122
import modelengine.fitframework.util.StringUtils;
@@ -172,6 +173,9 @@ private List<ValidationMetadata> getValidationFields(Type validationObject, Obje
172173
private List<ValidationMetadata> handleCollection(Type[] actualTypeArgs, Collection<?> validationValueCollection,
173174
Method method, Class<?>[] validationGroups) {
174175
Validation.equals(actualTypeArgs.length, 1, "The collection must have exactly 1 parameterized type.");
176+
if (CollectionUtils.isEmpty(validationValueCollection)) {
177+
return Collections.emptyList();
178+
}
175179
return validationValueCollection.stream()
176180
.flatMap(element -> this.getValidationFields(actualTypeArgs[0], element, method, validationGroups)
177181
.stream())
@@ -181,6 +185,9 @@ private List<ValidationMetadata> handleCollection(Type[] actualTypeArgs, Collect
181185
private List<ValidationMetadata> handleMap(Type[] actualTypeArgs, Map<?, ?> validationValueMap, Method method,
182186
Class<?>[] validationGroups) {
183187
Validation.equals(actualTypeArgs.length, 2, "The map must have exactly 2 parameterized types.");
188+
if (MapUtils.isEmpty(validationValueMap)) {
189+
return Collections.emptyList();
190+
}
184191
return validationValueMap.entrySet()
185192
.stream()
186193
.flatMap(entry -> Stream.concat(

framework/fit/java/fit-extension/fit-validation/src/test/java/modelengine/fitframework/validation/ValidationDataControllerTest.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*---------------------------------------------------------------------------------------------
2-
* Copyright (c) 2024 Huawei Technologies Co., Ltd. All rights reserved.
2+
* Copyright (c) 2024-2025 Huawei Technologies Co., Ltd. All rights reserved.
33
* This file is a part of the ModelEngine Project.
44
* Licensed under the MIT License. See License.txt in the project root for license information.
55
*--------------------------------------------------------------------------------------------*/
@@ -23,6 +23,8 @@
2323
import org.junit.jupiter.api.Test;
2424

2525
import java.io.IOException;
26+
import java.util.Arrays;
27+
import java.util.Collections;
2628

2729
/**
2830
* {@link ValidationDataController} 的测试集。
@@ -104,4 +106,36 @@ void shouldFailedWhenCreateInvalidProduct() {
104106
this.response = this.mockMvc.perform(requestBuilder);
105107
assertThat(this.response.statusCode()).isEqualTo(500);
106108
}
109+
110+
@Test
111+
@DisplayName("合法 Product-List<Car> 对象校验: cars == null")
112+
void shouldOkWhenCreateInvalidProductWithNoCar() {
113+
Product product = new Product("mac", 10499.0, 100, "computer", null);
114+
MockRequestBuilder requestBuilder =
115+
MockMvcRequestBuilders.post("/validation/product/default").jsonEntity(product).responseType(Void.class);
116+
this.response = this.mockMvc.perform(requestBuilder);
117+
assertThat(this.response.statusCode()).isEqualTo(200);
118+
}
119+
120+
@Test
121+
@DisplayName("合法 Product-List<Car> 对象校验: cars.size() == 1")
122+
void shouldOkWhenCreateInvalidProductWith1Car() {
123+
Car validCar = new Car(1, 1, "brand", "model", 2000, 1999);
124+
Product product = new Product("mac", 10499.0, 100, "computer", Collections.singletonList(validCar));
125+
MockRequestBuilder requestBuilder =
126+
MockMvcRequestBuilders.post("/validation/product/default").jsonEntity(product).responseType(Void.class);
127+
this.response = this.mockMvc.perform(requestBuilder);
128+
assertThat(this.response.statusCode()).isEqualTo(200);
129+
}
130+
131+
@Test
132+
@DisplayName("不合法 Product-List<Car> 对象校验: cars.size() == 2")
133+
void shouldFailedWhenCreateInvalidProductWith2Cars() {
134+
Car validCar = new Car(1, 1, "brand", "model", 2000, 1999);
135+
Product product = new Product("mac", 10499.0, 100, "computer", Arrays.asList(validCar, validCar));
136+
MockRequestBuilder requestBuilder =
137+
MockMvcRequestBuilders.post("/validation/product/default").jsonEntity(product).responseType(Void.class);
138+
this.response = this.mockMvc.perform(requestBuilder);
139+
assertThat(this.response.statusCode()).isEqualTo(500);
140+
}
107141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fitframework.validation.annotation;
8+
9+
import modelengine.fitframework.validation.Validated;
10+
import modelengine.fitframework.validation.constraints.Constraint;
11+
import modelengine.fitframework.validation.validator.MaxSizeValidator;
12+
13+
import java.lang.annotation.Retention;
14+
import java.lang.annotation.RetentionPolicy;
15+
16+
/**
17+
* 表示集合元素数量限制的测试注解类。
18+
*
19+
* @author 李金绪
20+
* @since 2025-03-17
21+
*/
22+
@Retention(RetentionPolicy.RUNTIME)
23+
@Constraint({MaxSizeValidator.class})
24+
@Validated
25+
public @interface MaxSize {
26+
/**
27+
* 表示集合元素的大小的上限值。
28+
*
29+
* @return 表示集合元素的大小的上限值的 {@code long}。
30+
*/
31+
long max();
32+
33+
/**
34+
* 表示校验失败的信息。
35+
*
36+
* @return 表示校验失败的信息的 {@link String}。
37+
*/
38+
String message() default "must be lesser than the max value.";
39+
40+
/**
41+
* 表示校验的分组。
42+
*
43+
* @return 表示校验分组的 {@link Class}{@code <?>[]}。
44+
*/
45+
Class<?>[] groups() default {};
46+
}

framework/fit/java/fit-extension/fit-validation/src/test/java/modelengine/fitframework/validation/data/Product.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
/*---------------------------------------------------------------------------------------------
2-
* Copyright (c) 2024 Huawei Technologies Co., Ltd. All rights reserved.
2+
* Copyright (c) 2024-2025 Huawei Technologies Co., Ltd. All rights reserved.
33
* This file is a part of the ModelEngine Project.
44
* Licensed under the MIT License. See License.txt in the project root for license information.
55
*--------------------------------------------------------------------------------------------*/
66

77
package modelengine.fitframework.validation.data;
88

9+
import modelengine.fitframework.validation.annotation.MaxSize;
910
import modelengine.fitframework.validation.constraints.NotBlank;
1011
import modelengine.fitframework.validation.constraints.Positive;
1112

13+
import java.util.List;
14+
1215
/**
1316
* 表示产品的数据类。
1417
*
@@ -28,16 +31,43 @@ public class Product {
2831
@NotBlank(message = "产品类别不能为空")
2932
private String category;
3033

34+
@MaxSize(max = 2)
35+
private List<Car> cars;
36+
3137
/**
3238
* Product 默认构造函数。
33-
*
3439
*/
3540
public Product() {}
3641

42+
/**
43+
* 构造函数。
44+
*
45+
* @param name 表示名字的 {@link String}。
46+
* @param price 表示价格的 {@link Double}。
47+
* @param quantity 表示数量的 {@link Integer}。
48+
* @param category 表示类别的 {@link String}。
49+
*/
3750
public Product(String name, Double price, Integer quantity, String category) {
3851
this.name = name;
3952
this.price = price;
4053
this.quantity = quantity;
4154
this.category = category;
4255
}
56+
57+
/**
58+
* 构造函数。
59+
*
60+
* @param name 表示名字的 {@link String}。
61+
* @param price 表示价格的 {@link Double}。
62+
* @param quantity 表示数量的 {@link Integer}。
63+
* @param category 表示类别的 {@link String}。
64+
* @param cars 表示汽车集合的 {@link List}{@code <}{@link Car}{@code >}。
65+
*/
66+
public Product(String name, Double price, Integer quantity, String category, List<Car> cars) {
67+
this.name = name;
68+
this.price = price;
69+
this.quantity = quantity;
70+
this.category = category;
71+
this.cars = cars;
72+
}
4373
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fitframework.validation.validator;
8+
9+
import static modelengine.fitframework.util.ObjectUtils.cast;
10+
11+
import modelengine.fitframework.validation.ConstraintValidator;
12+
import modelengine.fitframework.validation.annotation.MaxSize;
13+
14+
import java.util.List;
15+
16+
/**
17+
* 表示单集合元素的测试校验类。
18+
*
19+
* @author 李金绪
20+
* @since 2025-03-17
21+
*/
22+
public class MaxSizeValidator implements ConstraintValidator<MaxSize, Object> {
23+
private long max;
24+
25+
@Override
26+
public void initialize(MaxSize constraintAnnotation) {
27+
this.max = constraintAnnotation.max();
28+
}
29+
30+
@Override
31+
public boolean isValid(Object value) {
32+
if (value == null) {
33+
return true;
34+
}
35+
if (!(value instanceof List)) {
36+
return false;
37+
}
38+
List<Object> valueList = cast(value);
39+
return valueList.size() < this.max;
40+
}
41+
}

0 commit comments

Comments
 (0)