Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
835108e5
Commit
835108e5
authored
Aug 09, 2019
by
Madhura Bhave
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support binding of YAML style true/false values to 'ON'/'OFF'.
Fixes gh-17798
parent
4928e958
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
214 additions
and
56 deletions
+214
-56
AbstractTypeToEnumConverterFactory.java
...work/boot/convert/AbstractTypeToEnumConverterFactory.java
+89
-0
ApplicationConversionService.java
...gframework/boot/convert/ApplicationConversionService.java
+1
-0
BooleanToEnumConverterFactory.java
...framework/boot/convert/BooleanToEnumConverterFactory.java
+50
-0
LenientStringToEnumConverterFactory.java
...ork/boot/convert/LenientStringToEnumConverterFactory.java
+6
-56
SpringApplicationTests.java
...java/org/springframework/boot/SpringApplicationTests.java
+9
-0
BooleanToEnumConverterFactoryTests.java
...work/boot/convert/BooleanToEnumConverterFactoryTests.java
+59
-0
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/AbstractTypeToEnumConverterFactory.java
0 → 100644
View file @
835108e5
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
convert
;
import
java.util.Collections
;
import
java.util.EnumSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.convert.converter.ConverterFactory
;
import
org.springframework.util.Assert
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
/**
* Abstract base class for converting from a type to a {@link java.lang.Enum}.
*
* @param <T> the source type
* @author Phillip Webb
* @author Madhura Bhave
*/
abstract
class
AbstractTypeToEnumConverterFactory
<
T
>
implements
ConverterFactory
<
T
,
Enum
>
{
private
static
Map
<
String
,
List
<
String
>>
ALIASES
;
static
{
MultiValueMap
<
String
,
String
>
aliases
=
new
LinkedMultiValueMap
<>();
aliases
.
add
(
"true"
,
"on"
);
aliases
.
add
(
"false"
,
"off"
);
ALIASES
=
Collections
.
unmodifiableMap
(
aliases
);
}
@Override
public
<
E
extends
Enum
>
Converter
<
T
,
E
>
getConverter
(
Class
<
E
>
targetType
)
{
Class
<?>
enumType
=
targetType
;
while
(
enumType
!=
null
&&
!
enumType
.
isEnum
())
{
enumType
=
enumType
.
getSuperclass
();
}
Assert
.
notNull
(
enumType
,
()
->
"The target type "
+
targetType
.
getName
()
+
" does not refer to an enum"
);
return
getTypeToEnumConverter
(
targetType
);
}
abstract
<
E
extends
Enum
>
Converter
<
T
,
E
>
getTypeToEnumConverter
(
Class
<
E
>
targetType
);
<
E
extends
Enum
>
E
findEnum
(
String
source
,
Class
<
E
>
enumType
)
{
Map
<
String
,
E
>
candidates
=
new
LinkedHashMap
<>();
for
(
E
candidate
:
(
Set
<
E
>)
EnumSet
.
allOf
(
enumType
))
{
candidates
.
put
(
getCanonicalName
(
candidate
.
name
()),
candidate
);
}
String
name
=
getCanonicalName
(
source
);
E
result
=
candidates
.
get
(
name
);
if
(
result
!=
null
)
{
return
result
;
}
for
(
String
alias
:
ALIASES
.
getOrDefault
(
name
,
Collections
.
emptyList
()))
{
result
=
candidates
.
get
(
alias
);
if
(
result
!=
null
)
{
return
result
;
}
}
throw
new
IllegalArgumentException
(
"No enum constant "
+
enumType
.
getCanonicalName
()
+
"."
+
source
);
}
private
String
getCanonicalName
(
String
name
)
{
StringBuilder
canonicalName
=
new
StringBuilder
(
name
.
length
());
name
.
chars
().
filter
(
Character:
:
isLetterOrDigit
).
map
(
Character:
:
toLowerCase
)
.
forEach
((
c
)
->
canonicalName
.
append
((
char
)
c
));
return
canonicalName
.
toString
();
}
}
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java
View file @
835108e5
...
...
@@ -116,6 +116,7 @@ public class ApplicationConversionService extends FormattingConversionService {
registry
.
addConverter
(
new
StringToDataSizeConverter
());
registry
.
addConverter
(
new
NumberToDataSizeConverter
());
registry
.
addConverterFactory
(
new
LenientStringToEnumConverterFactory
());
registry
.
addConverterFactory
(
new
BooleanToEnumConverterFactory
());
}
/**
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/BooleanToEnumConverterFactory.java
0 → 100644
View file @
835108e5
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
convert
;
import
org.springframework.core.convert.converter.Converter
;
/**
* Converter to support mapping of YAML style {@code "false"} and {@code "true"} to enums
* {@code ON} and {@code OFF}.
*
* @author Madhura Bhave
*/
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
final
class
BooleanToEnumConverterFactory
extends
AbstractTypeToEnumConverterFactory
<
Boolean
>
{
@Override
<
E
extends
Enum
>
Converter
<
Boolean
,
E
>
getTypeToEnumConverter
(
Class
<
E
>
targetType
)
{
return
new
BooleanToEnum
<>(
targetType
);
}
private
class
BooleanToEnum
<
T
extends
Enum
>
implements
Converter
<
Boolean
,
T
>
{
private
final
Class
<
T
>
enumType
;
BooleanToEnum
(
Class
<
T
>
enumType
)
{
this
.
enumType
=
enumType
;
}
@Override
public
T
convert
(
Boolean
source
)
{
return
findEnum
(
Boolean
.
toString
(
source
),
this
.
enumType
);
}
}
}
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/LenientStringToEnumConverterFactory.java
View file @
835108e5
...
...
@@ -16,18 +16,7 @@
package
org
.
springframework
.
boot
.
convert
;
import
java.util.Collections
;
import
java.util.EnumSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.convert.converter.ConverterFactory
;
import
org.springframework.util.Assert
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
/**
* Converts from a String to a {@link java.lang.Enum} with lenient conversion rules.
...
...
@@ -35,31 +24,18 @@ import org.springframework.util.MultiValueMap;
* <ul>
* <li>Uses a case insensitive search</li>
* <li>Does not consider {@code '_'}, {@code '$'} or other special characters</li>
* <li>Allows mapping of
YAML style {@code "false"} and {@code "true"} to enums {@code ON}
*
and
{@code OFF}</li>
* <li>Allows mapping of
{@code "false"} and {@code "true"} to enums {@code ON} and
* {@code OFF}</li>
* </ul>
*
* @author Phillip Webb
*/
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
final
class
LenientStringToEnumConverterFactory
implements
ConverterFactory
<
String
,
Enum
>
{
private
static
Map
<
String
,
List
<
String
>>
ALIASES
;
static
{
MultiValueMap
<
String
,
String
>
aliases
=
new
LinkedMultiValueMap
<>();
aliases
.
add
(
"true"
,
"on"
);
aliases
.
add
(
"false"
,
"off"
);
ALIASES
=
Collections
.
unmodifiableMap
(
aliases
);
}
final
class
LenientStringToEnumConverterFactory
extends
AbstractTypeToEnumConverterFactory
<
String
>
{
@Override
public
<
T
extends
Enum
>
Converter
<
String
,
T
>
getConverter
(
Class
<
T
>
targetType
)
{
Class
<?>
enumType
=
targetType
;
while
(
enumType
!=
null
&&
!
enumType
.
isEnum
())
{
enumType
=
enumType
.
getSuperclass
();
}
Assert
.
notNull
(
enumType
,
()
->
"The target type "
+
targetType
.
getName
()
+
" does not refer to an enum"
);
return
new
StringToEnum
(
enumType
);
<
E
extends
Enum
>
Converter
<
String
,
E
>
getTypeToEnumConverter
(
Class
<
E
>
targetType
)
{
return
new
StringToEnum
<>(
targetType
);
}
private
class
StringToEnum
<
T
extends
Enum
>
implements
Converter
<
String
,
T
>
{
...
...
@@ -80,36 +56,10 @@ final class LenientStringToEnumConverterFactory implements ConverterFactory<Stri
return
(
T
)
Enum
.
valueOf
(
this
.
enumType
,
source
);
}
catch
(
Exception
ex
)
{
return
findEnum
(
source
);
return
findEnum
(
source
,
this
.
enumType
);
}
}
private
T
findEnum
(
String
source
)
{
Map
<
String
,
T
>
candidates
=
new
LinkedHashMap
<
String
,
T
>();
for
(
T
candidate
:
(
Set
<
T
>)
EnumSet
.
allOf
(
this
.
enumType
))
{
candidates
.
put
(
getCanonicalName
(
candidate
.
name
()),
candidate
);
}
String
name
=
getCanonicalName
(
source
);
T
result
=
candidates
.
get
(
name
);
if
(
result
!=
null
)
{
return
result
;
}
for
(
String
alias
:
ALIASES
.
getOrDefault
(
name
,
Collections
.
emptyList
()))
{
result
=
candidates
.
get
(
alias
);
if
(
result
!=
null
)
{
return
result
;
}
}
throw
new
IllegalArgumentException
(
"No enum constant "
+
this
.
enumType
.
getCanonicalName
()
+
"."
+
source
);
}
private
String
getCanonicalName
(
String
name
)
{
StringBuilder
canonicalName
=
new
StringBuilder
(
name
.
length
());
name
.
chars
().
filter
(
Character:
:
isLetterOrDigit
).
map
(
Character:
:
toLowerCase
)
.
forEach
((
c
)
->
canonicalName
.
append
((
char
)
c
));
return
canonicalName
.
toString
();
}
}
}
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java
View file @
835108e5
...
...
@@ -290,6 +290,15 @@ class SpringApplicationTests {
@Test
void
bindsYamlStyleBannerModeToSpringApplication
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setDefaultProperties
(
Collections
.
singletonMap
(
"spring.main.banner-mode"
,
false
));
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
this
.
context
=
application
.
run
();
assertThat
(
application
).
hasFieldOrPropertyWithValue
(
"bannerMode"
,
Banner
.
Mode
.
OFF
);
}
@Test
void
bindsBooleanAsStringBannerModeToSpringApplication
()
{
SpringApplication
application
=
new
SpringApplication
(
ExampleConfig
.
class
);
application
.
setWebApplicationType
(
WebApplicationType
.
NONE
);
this
.
context
=
application
.
run
(
"--spring.main.banner-mode=false"
);
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/convert/BooleanToEnumConverterFactoryTests.java
0 → 100644
View file @
835108e5
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
convert
;
import
java.util.stream.Stream
;
import
org.junit.jupiter.params.provider.Arguments
;
import
org.springframework.core.convert.ConversionService
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link BooleanToEnumConverterFactory}.
*
* @author Madhura Bhave
*/
class
BooleanToEnumConverterFactoryTests
{
@ConversionServiceTest
void
convertFromBooleanToEnumWhenShouldConvertValue
(
ConversionService
conversionService
)
{
assertThat
(
conversionService
.
convert
(
true
,
TestOnOffEnum
.
class
)).
isEqualTo
(
TestOnOffEnum
.
ON
);
assertThat
(
conversionService
.
convert
(
false
,
TestOnOffEnum
.
class
)).
isEqualTo
(
TestOnOffEnum
.
OFF
);
assertThat
(
conversionService
.
convert
(
true
,
TestTrueFalseEnum
.
class
)).
isEqualTo
(
TestTrueFalseEnum
.
TRUE
);
assertThat
(
conversionService
.
convert
(
false
,
TestTrueFalseEnum
.
class
)).
isEqualTo
(
TestTrueFalseEnum
.
FALSE
);
}
static
Stream
<?
extends
Arguments
>
conversionServices
()
{
return
ConversionServiceArguments
.
with
((
service
)
->
service
.
addConverterFactory
(
new
BooleanToEnumConverterFactory
()));
}
enum
TestOnOffEnum
{
ON
,
OFF
}
enum
TestTrueFalseEnum
{
ONE
,
TWO
,
TRUE
,
FALSE
,
ON
,
OFF
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment