Skip to content

Commit 5d9836b

Browse files
committed
Refine unmapped property support
Replace `@UnmappedPropertyValue` with a `skip` attribute on `@PropertyMapping` so that any default attribute value can be skipped. Closes gh-6455
1 parent ac1ad2a commit 5d9836b

File tree

6 files changed

+51
-45
lines changed

6 files changed

+51
-45
lines changed

spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.boot.test.autoconfigure.properties;
1818

1919
import java.lang.annotation.Annotation;
20-
import java.lang.reflect.Field;
2120
import java.lang.reflect.Method;
2221
import java.util.ArrayList;
2322
import java.util.Collections;
@@ -110,33 +109,32 @@ private void collectProperties(Annotation annotation, Method attribute,
110109
PropertyMapping typeMapping, Map<String, Object> properties) {
111110
PropertyMapping attributeMapping = AnnotationUtils.getAnnotation(attribute,
112111
PropertyMapping.class);
113-
if (isMapped(typeMapping, attributeMapping)) {
114-
String name = getName(typeMapping, attributeMapping, attribute);
115-
ReflectionUtils.makeAccessible(attribute);
116-
Object value = ReflectionUtils.invokeMethod(attribute, annotation);
117-
if (isValueMapped(value)) {
118-
putProperties(name, value, properties);
112+
SkipPropertyMapping skip = getMappingType(typeMapping, attributeMapping);
113+
if (skip == SkipPropertyMapping.YES) {
114+
return;
115+
}
116+
String name = getName(typeMapping, attributeMapping, attribute);
117+
ReflectionUtils.makeAccessible(attribute);
118+
Object value = ReflectionUtils.invokeMethod(attribute, annotation);
119+
if (skip == SkipPropertyMapping.ON_DEFAULT_VALUE) {
120+
Object defaultValue = AnnotationUtils.getDefaultValue(annotation,
121+
attribute.getName());
122+
if (ObjectUtils.nullSafeEquals(value, defaultValue)) {
123+
return;
119124
}
120125
}
126+
putProperties(name, value, properties);
121127
}
122128

123-
private boolean isMapped(PropertyMapping typeMapping,
129+
private SkipPropertyMapping getMappingType(PropertyMapping typeMapping,
124130
PropertyMapping attributeMapping) {
125131
if (attributeMapping != null) {
126-
return attributeMapping.map();
132+
return attributeMapping.skip();
127133
}
128-
return (typeMapping != null && typeMapping.map());
129-
}
130-
131-
private boolean isValueMapped(Object value) {
132-
if (value != null && value instanceof Enum) {
133-
Field field = ReflectionUtils.findField(value.getClass(),
134-
((Enum<?>) value).name());
135-
if (AnnotatedElementUtils.isAnnotated(field, UnmappedPropertyValue.class)) {
136-
return false;
137-
}
134+
if (typeMapping != null) {
135+
return typeMapping.skip();
138136
}
139-
return true;
137+
return SkipPropertyMapping.YES;
140138
}
141139

142140
private String getName(PropertyMapping typeMapping, PropertyMapping attributeMapping,

spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/PropertyMapping.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
* @author Phillip Webb
4848
* @since 1.4.0
4949
* @see AnnotationsPropertySource
50-
* @see UnmappedPropertyValue
5150
* @see TestPropertySource
5251
*/
5352
@Documented
@@ -64,11 +63,11 @@
6463
String value() default "";
6564

6665
/**
67-
* Determines if mapping should occur. When specified at the type-level indicates if
68-
* mapping should occur by default or not. When used at the attribute-level, overrides
69-
* the type-level default.
70-
* @return if mapping should occur
66+
* Determines if mapping should be skipped. When specified at the type-level indicates
67+
* if skipping should occur by default or not. When used at the attribute-level,
68+
* overrides the type-level default.
69+
* @return if mapping should be skipped
7170
*/
72-
boolean map() default true;
71+
SkipPropertyMapping skip() default SkipPropertyMapping.NO;
7372

7473
}
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,27 @@
1616

1717
package org.springframework.boot.test.autoconfigure.properties;
1818

19-
import java.lang.annotation.ElementType;
20-
import java.lang.annotation.Retention;
21-
import java.lang.annotation.RetentionPolicy;
22-
import java.lang.annotation.Target;
23-
2419
/**
25-
* Indicates that a single value should not be mapped when referenced from a
26-
* {@link PropertyMapping @PropertyMapping} annotation.
20+
* Enum used to control when {@link PropertyMapping} is skipped.
2721
*
2822
* @author Phillip Webb
2923
* @since 1.4.0
30-
* @see PropertyMapping
3124
*/
32-
@Retention(RetentionPolicy.RUNTIME)
33-
@Target({ ElementType.FIELD })
34-
public @interface UnmappedPropertyValue {
25+
public enum SkipPropertyMapping {
26+
27+
/**
28+
* Skip the mapping the property.
29+
*/
30+
YES,
31+
32+
/**
33+
* Skip mapping the property when the default attribute value is specified.
34+
*/
35+
ON_DEFAULT_VALUE,
36+
37+
/**
38+
* Don't skip mapping the property.
39+
*/
40+
NO,
3541

3642
}

spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
2929
import org.springframework.boot.test.autoconfigure.properties.PropertyMapping;
30+
import org.springframework.boot.test.autoconfigure.properties.SkipPropertyMapping;
3031
import org.springframework.test.web.servlet.MockMvc;
3132
import org.springframework.test.web.servlet.MvcResult;
3233

@@ -57,6 +58,7 @@
5758
* How {@link MvcResult} information should be printed after each MockMVC invocation.
5859
* @return how information is printed
5960
*/
61+
@PropertyMapping(skip = SkipPropertyMapping.ON_DEFAULT_VALUE)
6062
MockMvcPrint print() default MockMvcPrint.DEFAULT;
6163

6264
/**

spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcPrint.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
package org.springframework.boot.test.autoconfigure.web.servlet;
1818

19-
import org.springframework.boot.test.autoconfigure.properties.UnmappedPropertyValue;
20-
2119
/**
2220
* MVC print options specified from {@link AutoConfigureMockMvc}.
2321
*
@@ -30,7 +28,7 @@ public enum MockMvcPrint {
3028
* Use the default print setting ({@code MockMvcPrint.SYSTEM_OUT} unless explicitly
3129
* overridden).
3230
*/
33-
@UnmappedPropertyValue DEFAULT,
31+
DEFAULT,
3432

3533
/**
3634
* Log MVC interactions at the {@code DEBUG} level.

spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static class NotMappedAtTypeLevel {
262262
}
263263

264264
@Retention(RetentionPolicy.RUNTIME)
265-
@PropertyMapping(map = false)
265+
@PropertyMapping(skip = SkipPropertyMapping.YES)
266266
static @interface NotMappedAtTypeLevelAnnotation {
267267

268268
@PropertyMapping
@@ -283,7 +283,7 @@ static class NotMappedAtAttributeLevel {
283283

284284
String value();
285285

286-
@PropertyMapping(map = false)
286+
@PropertyMapping(skip = SkipPropertyMapping.YES)
287287
String ignore() default "xyz";
288288

289289
}
@@ -362,7 +362,9 @@ static class PropertyMappedAttributeWithAnAlias {
362362
static @interface AttributeWithAliasAnnotation {
363363

364364
@AliasFor(annotation = AliasedAttributeAnnotation.class, attribute = "value")
365-
String value() default "foo";
365+
String value()
366+
367+
default "foo";
366368

367369
String someOtherAttribute() default "shouldNotBeMapped";
368370

@@ -410,13 +412,14 @@ static class EnumValueNotMapped {
410412
@PropertyMapping("testenum")
411413
static @interface EnumAnnotation {
412414

413-
EnumItem value();
415+
@PropertyMapping(skip = SkipPropertyMapping.ON_DEFAULT_VALUE)
416+
EnumItem value() default EnumItem.DEFAULT;
414417

415418
}
416419

417420
enum EnumItem {
418421

419-
@UnmappedPropertyValue DEFAULT,
422+
DEFAULT,
420423

421424
ONE,
422425

0 commit comments

Comments
 (0)