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
1448902c
Commit
1448902c
authored
Oct 28, 2016
by
Stephane Nicoll
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1.5.x'
parents
a02fd93d
f6959ccb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
189 additions
and
19 deletions
+189
-19
appendix-configuration-metadata.adoc
...cs/src/main/asciidoc/appendix-configuration-metadata.adoc
+7
-6
ConfigurationMetadataAnnotationProcessor.java
...onprocessor/ConfigurationMetadataAnnotationProcessor.java
+7
-7
MetadataCollector.java
...mework/boot/configurationprocessor/MetadataCollector.java
+1
-1
TypeUtils.java
...pringframework/boot/configurationprocessor/TypeUtils.java
+37
-5
ConfigurationMetadataAnnotationProcessorTests.java
...cessor/ConfigurationMetadataAnnotationProcessorTests.java
+30
-0
GenericConfig.java
...work/boot/configurationsample/specific/GenericConfig.java
+107
-0
No files found.
spring-boot-docs/src/main/asciidoc/appendix-configuration-metadata.adoc
View file @
1448902c
...
...
@@ -164,12 +164,13 @@ The JSON object contained in the `properties` array can contain the following at
|`type`
| String
| The class name of the data type of the property. For example, `java.lang.String`. This
attribute can be used to guide the user as to the types of values that they can enter.
For consistency, the type of a primitive is specified using its wrapper counterpart,
i.e. `boolean` becomes `java.lang.Boolean`. Note that this class may be a complex type
that gets converted from a String as values are bound. May be omitted if the type is
not known.
| The full signature of the data type of the property. For example, `java.lang.String`
but also a full generic type such as `java.util.Map<java.util.String,acme.MyEnum>`.
This attribute can be used to guide the user as to the types of values that they can
enter. For consistency, the type of a primitive is specified using its wrapper
counterpart, i.e. `boolean` becomes `java.lang.Boolean`. Note that this class may be
a complex type that gets converted from a String as values are bound. May be omitted
if the type is not known.
|`description`
| String
...
...
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java
View file @
1448902c
...
...
@@ -161,7 +161,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
}
private
void
processAnnotatedTypeElement
(
String
prefix
,
TypeElement
element
)
{
String
type
=
this
.
typeUtils
.
get
Typ
e
(
element
);
String
type
=
this
.
typeUtils
.
get
QualifiedNam
e
(
element
);
this
.
metadataCollector
.
add
(
ItemMetadata
.
newGroup
(
prefix
,
type
,
type
,
null
));
processTypeElement
(
prefix
,
element
,
null
);
}
...
...
@@ -173,8 +173,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
.
asElement
(
element
.
getReturnType
());
if
(
returns
instanceof
TypeElement
)
{
ItemMetadata
group
=
ItemMetadata
.
newGroup
(
prefix
,
this
.
typeUtils
.
get
Typ
e
(
returns
),
this
.
typeUtils
.
get
Typ
e
(
element
.
getEnclosingElement
()),
this
.
typeUtils
.
get
QualifiedNam
e
(
returns
),
this
.
typeUtils
.
get
QualifiedNam
e
(
element
.
getEnclosingElement
()),
element
.
toString
());
if
(
this
.
metadataCollector
.
hasSimilarGroup
(
group
))
{
this
.
processingEnv
.
getMessager
().
printMessage
(
Kind
.
ERROR
,
...
...
@@ -226,7 +226,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
boolean
isCollection
=
this
.
typeUtils
.
isCollectionOrMap
(
returnType
);
if
(!
isExcluded
&&
!
isNested
&&
(
setter
!=
null
||
isCollection
))
{
String
dataType
=
this
.
typeUtils
.
getType
(
returnType
);
String
sourceType
=
this
.
typeUtils
.
get
Typ
e
(
element
);
String
sourceType
=
this
.
typeUtils
.
get
QualifiedNam
e
(
element
);
String
description
=
this
.
typeUtils
.
getJavaDoc
(
field
);
Object
defaultValue
=
fieldValues
.
get
(
name
);
boolean
deprecated
=
isDeprecated
(
getter
)
||
isDeprecated
(
setter
)
...
...
@@ -270,7 +270,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
boolean
hasSetter
=
hasLombokSetter
(
field
,
element
);
if
(!
isExcluded
&&
!
isNested
&&
(
hasSetter
||
isCollection
))
{
String
dataType
=
this
.
typeUtils
.
getType
(
returnType
);
String
sourceType
=
this
.
typeUtils
.
get
Typ
e
(
element
);
String
sourceType
=
this
.
typeUtils
.
get
QualifiedNam
e
(
element
);
String
description
=
this
.
typeUtils
.
getJavaDoc
(
field
);
Object
defaultValue
=
fieldValues
.
get
(
name
);
boolean
deprecated
=
isDeprecated
(
field
)
||
isDeprecated
(
source
);
...
...
@@ -329,8 +329,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
&&
annotation
==
null
&&
isNested
)
{
String
nestedPrefix
=
ConfigurationMetadata
.
nestedPrefix
(
prefix
,
name
);
this
.
metadataCollector
.
add
(
ItemMetadata
.
newGroup
(
nestedPrefix
,
this
.
typeUtils
.
get
Typ
e
(
returnElement
),
this
.
typeUtils
.
get
Typ
e
(
element
),
this
.
typeUtils
.
get
QualifiedNam
e
(
returnElement
),
this
.
typeUtils
.
get
QualifiedNam
e
(
element
),
(
getter
==
null
?
null
:
getter
.
toString
())));
processTypeElement
(
nestedPrefix
,
(
TypeElement
)
returnElement
,
source
);
}
...
...
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataCollector.java
View file @
1448902c
...
...
@@ -69,7 +69,7 @@ public class MetadataCollector {
private
void
markAsProcessed
(
Element
element
)
{
if
(
element
instanceof
TypeElement
)
{
this
.
processedSourceTypes
.
add
(
this
.
typeUtils
.
get
Typ
e
(
element
));
this
.
processedSourceTypes
.
add
(
this
.
typeUtils
.
get
QualifiedNam
e
(
element
));
}
}
...
...
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java
View file @
1448902c
...
...
@@ -93,10 +93,34 @@ class TypeUtils {
}
}
public
String
getType
(
Element
element
)
{
return
getType
(
element
==
null
?
null
:
element
.
asType
());
/**
* Return the qualified name of the specified element.
* @param element the element to handle
* @return the fully qualified name of the element, suitable for a call
* to {@link Class#forName(String)}
*/
public
String
getQualifiedName
(
Element
element
)
{
if
(
element
==
null
)
{
return
null
;
}
TypeElement
enclosingElement
=
getEnclosingTypeElement
(
element
.
asType
());
if
(
enclosingElement
!=
null
)
{
return
getQualifiedName
(
enclosingElement
)
+
"$"
+
((
DeclaredType
)
element
.
asType
()).
asElement
().
getSimpleName
().
toString
();
}
if
(
element
instanceof
TypeElement
)
{
return
((
TypeElement
)
element
).
getQualifiedName
().
toString
();
}
throw
new
IllegalStateException
(
"Could not extract qualified name from "
+
element
);
}
/**
* Return the type of the specified {@link TypeMirror} including all its generic
* information.
* @param type the type to handle
* @return a representation of the type including all its generic information
*/
public
String
getType
(
TypeMirror
type
)
{
if
(
type
==
null
)
{
return
null
;
...
...
@@ -105,15 +129,23 @@ class TypeUtils {
if
(
wrapper
!=
null
)
{
return
wrapper
.
getName
();
}
TypeElement
enclosingElement
=
getEnclosingTypeElement
(
type
);
if
(
enclosingElement
!=
null
)
{
return
getQualifiedName
(
enclosingElement
)
+
"$"
+
((
DeclaredType
)
type
).
asElement
().
getSimpleName
().
toString
();
}
return
type
.
toString
();
}
private
TypeElement
getEnclosingTypeElement
(
TypeMirror
type
)
{
if
(
type
instanceof
DeclaredType
)
{
DeclaredType
declaredType
=
(
DeclaredType
)
type
;
Element
enclosingElement
=
declaredType
.
asElement
().
getEnclosingElement
();
if
(
enclosingElement
!=
null
&&
enclosingElement
instanceof
TypeElement
)
{
return
getType
(
enclosingElement
)
+
"$"
+
declaredType
.
asElement
().
getSimpleName
().
toString
();
return
(
TypeElement
)
enclosingElement
;
}
}
return
type
.
toString
()
;
return
null
;
}
public
boolean
isCollectionOrMap
(
TypeMirror
type
)
{
...
...
spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java
View file @
1448902c
...
...
@@ -59,6 +59,7 @@ import org.springframework.boot.configurationsample.specific.BuilderPojo;
import
org.springframework.boot.configurationsample.specific.DeprecatedUnrelatedMethodPojo
;
import
org.springframework.boot.configurationsample.specific.DoubleRegistrationProperties
;
import
org.springframework.boot.configurationsample.specific.ExcludedTypesPojo
;
import
org.springframework.boot.configurationsample.specific.GenericConfig
;
import
org.springframework.boot.configurationsample.specific.InnerClassAnnotatedGetterConfig
;
import
org.springframework.boot.configurationsample.specific.InnerClassProperties
;
import
org.springframework.boot.configurationsample.specific.InnerClassRootConfig
;
...
...
@@ -391,6 +392,35 @@ public class ConfigurationMetadataAnnotationProcessorTests {
compile
(
InvalidDoubleRegistrationProperties
.
class
);
}
@Test
public
void
genericTypes
()
throws
IOException
{
ConfigurationMetadata
metadata
=
compile
(
GenericConfig
.
class
);
assertThat
(
metadata
).
has
(
Metadata
.
withGroup
(
"generic"
).
ofType
(
"org.springframework.boot.configurationsample.specific.GenericConfig"
));
assertThat
(
metadata
).
has
(
Metadata
.
withGroup
(
"generic.foo"
).
ofType
(
"org.springframework.boot.configurationsample.specific.GenericConfig$Foo"
));
assertThat
(
metadata
).
has
(
Metadata
.
withGroup
(
"generic.foo.bar"
).
ofType
(
"org.springframework.boot.configurationsample.specific.GenericConfig$Bar"
));
assertThat
(
metadata
).
has
(
Metadata
.
withGroup
(
"generic.foo.bar.biz"
).
ofType
(
"org.springframework.boot.configurationsample.specific.GenericConfig$Bar$Biz"
));
assertThat
(
metadata
).
has
(
Metadata
.
withProperty
(
"generic.foo.name"
)
.
ofType
(
String
.
class
)
.
fromSource
(
GenericConfig
.
Foo
.
class
));
assertThat
(
metadata
).
has
(
Metadata
.
withProperty
(
"generic.foo.string-to-bar"
)
.
ofType
(
"java.util.Map<java.lang.String,org.springframework.boot.configurationsample.specific.GenericConfig.Bar<java.lang.Integer>>"
)
.
fromSource
(
GenericConfig
.
Foo
.
class
));
assertThat
(
metadata
).
has
(
Metadata
.
withProperty
(
"generic.foo.string-to-integer"
)
.
ofType
(
"java.util.Map<java.lang.String,java.lang.Integer>"
)
.
fromSource
(
GenericConfig
.
Foo
.
class
));
assertThat
(
metadata
).
has
(
Metadata
.
withProperty
(
"generic.foo.bar.name"
)
.
ofType
(
"java.lang.String"
)
.
fromSource
(
GenericConfig
.
Bar
.
class
));
assertThat
(
metadata
).
has
(
Metadata
.
withProperty
(
"generic.foo.bar.biz.name"
)
.
ofType
(
"java.lang.String"
)
.
fromSource
(
GenericConfig
.
Bar
.
Biz
.
class
));
assertThat
(
metadata
.
getItems
()).
hasSize
(
9
);
}
@Test
public
void
lombokDataProperties
()
throws
Exception
{
ConfigurationMetadata
metadata
=
compile
(
LombokSimpleDataProperties
.
class
);
...
...
spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/GenericConfig.java
0 → 100644
View file @
1448902c
/*
* Copyright 2012-2016 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
*
* http://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
.
configurationsample
.
specific
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.springframework.boot.configurationsample.ConfigurationProperties
;
import
org.springframework.boot.configurationsample.NestedConfigurationProperty
;
/**
* Demonstrate that only relevant generics are stored in the metadata.
*
* @author Stephane Nicoll
*/
@ConfigurationProperties
(
"generic"
)
public
class
GenericConfig
<
T
>
{
private
final
Foo
foo
=
new
Foo
();
public
Foo
getFoo
()
{
return
this
.
foo
;
}
public
static
class
Foo
{
private
String
name
;
@NestedConfigurationProperty
private
final
Bar
<
String
>
bar
=
new
Bar
<
String
>();
private
final
Map
<
String
,
Bar
<
Integer
>>
stringToBar
=
new
HashMap
<
String
,
Bar
<
Integer
>>();
private
final
Map
<
String
,
Integer
>
stringToInteger
=
new
HashMap
<
String
,
Integer
>();
public
String
getName
()
{
return
this
.
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
Bar
<
String
>
getBar
()
{
return
this
.
bar
;
}
public
Map
<
String
,
Bar
<
Integer
>>
getStringToBar
()
{
return
this
.
stringToBar
;
}
public
Map
<
String
,
Integer
>
getStringToInteger
()
{
return
this
.
stringToInteger
;
}
}
public
static
class
Bar
<
U
>
{
private
String
name
;
@NestedConfigurationProperty
private
final
Biz
<
String
>
biz
=
new
Biz
<
String
>();
public
String
getName
()
{
return
this
.
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
Biz
<
String
>
getBiz
()
{
return
this
.
biz
;
}
public
static
class
Biz
<
V
>
{
private
String
name
;
public
String
getName
()
{
return
this
.
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
}
}
}
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