Merge branch '1.3.x' into 1.4.x
This commit is contained in:
		
						commit
						7f8849c62b
					
				|  | @ -164,12 +164,13 @@ The JSON object contained in the `properties` array can contain the following at | ||||||
| 
 | 
 | ||||||
| |`type` | |`type` | ||||||
| | String | | String | ||||||
| | The class name of the data type of the property. For example, `java.lang.String`. This | | The full signature of the data type of the property. For example, `java.lang.String` | ||||||
|   attribute can be used to guide the user as to the types of values that they can enter. |   but also a full generic type such as `java.util.Map<java.util.String,acme.MyEnum>`. | ||||||
|   For consistency, the type of a primitive is specified using its wrapper counterpart, |   This attribute can be used to guide the user as to the types of values that they can | ||||||
|   i.e. `boolean` becomes `java.lang.Boolean`. Note that this class may be a complex type |   enter. For consistency, the type of a primitive is specified using its wrapper | ||||||
|   that gets converted from a String as values are bound. May be omitted if the type is |   counterpart, i.e. `boolean` becomes `java.lang.Boolean`. Note that this class may be | ||||||
|   not known. |   a complex type that gets converted from a String as values are bound. May be omitted | ||||||
|  |   if the type is not known. | ||||||
| 
 | 
 | ||||||
| |`description` | |`description` | ||||||
| | String | | String | ||||||
|  |  | ||||||
|  | @ -161,7 +161,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void processAnnotatedTypeElement(String prefix, TypeElement element) { | 	private void processAnnotatedTypeElement(String prefix, TypeElement element) { | ||||||
| 		String type = this.typeUtils.getType(element); | 		String type = this.typeUtils.getQualifiedName(element); | ||||||
| 		this.metadataCollector.add(ItemMetadata.newGroup(prefix, type, type, null)); | 		this.metadataCollector.add(ItemMetadata.newGroup(prefix, type, type, null)); | ||||||
| 		processTypeElement(prefix, element); | 		processTypeElement(prefix, element); | ||||||
| 	} | 	} | ||||||
|  | @ -173,8 +173,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | ||||||
| 					.asElement(element.getReturnType()); | 					.asElement(element.getReturnType()); | ||||||
| 			if (returns instanceof TypeElement) { | 			if (returns instanceof TypeElement) { | ||||||
| 				ItemMetadata group = ItemMetadata.newGroup(prefix, | 				ItemMetadata group = ItemMetadata.newGroup(prefix, | ||||||
| 						this.typeUtils.getType(returns), | 						this.typeUtils.getQualifiedName(returns), | ||||||
| 						this.typeUtils.getType(element.getEnclosingElement()), | 						this.typeUtils.getQualifiedName(element.getEnclosingElement()), | ||||||
| 						element.toString()); | 						element.toString()); | ||||||
| 				if (this.metadataCollector.hasSimilarGroup(group)) { | 				if (this.metadataCollector.hasSimilarGroup(group)) { | ||||||
| 					this.processingEnv.getMessager().printMessage(Kind.ERROR, | 					this.processingEnv.getMessager().printMessage(Kind.ERROR, | ||||||
|  | @ -224,7 +224,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | ||||||
| 			boolean isCollection = this.typeUtils.isCollectionOrMap(returnType); | 			boolean isCollection = this.typeUtils.isCollectionOrMap(returnType); | ||||||
| 			if (!isExcluded && !isNested && (setter != null || isCollection)) { | 			if (!isExcluded && !isNested && (setter != null || isCollection)) { | ||||||
| 				String dataType = this.typeUtils.getType(returnType); | 				String dataType = this.typeUtils.getType(returnType); | ||||||
| 				String sourceType = this.typeUtils.getType(element); | 				String sourceType = this.typeUtils.getQualifiedName(element); | ||||||
| 				String description = this.typeUtils.getJavaDoc(field); | 				String description = this.typeUtils.getJavaDoc(field); | ||||||
| 				Object defaultValue = fieldValues.get(name); | 				Object defaultValue = fieldValues.get(name); | ||||||
| 				boolean deprecated = isDeprecated(getter) || isDeprecated(setter) | 				boolean deprecated = isDeprecated(getter) || isDeprecated(setter) | ||||||
|  | @ -267,7 +267,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | ||||||
| 			boolean hasSetter = hasLombokSetter(field, element); | 			boolean hasSetter = hasLombokSetter(field, element); | ||||||
| 			if (!isExcluded && !isNested && (hasSetter || isCollection)) { | 			if (!isExcluded && !isNested && (hasSetter || isCollection)) { | ||||||
| 				String dataType = this.typeUtils.getType(returnType); | 				String dataType = this.typeUtils.getType(returnType); | ||||||
| 				String sourceType = this.typeUtils.getType(element); | 				String sourceType = this.typeUtils.getQualifiedName(element); | ||||||
| 				String description = this.typeUtils.getJavaDoc(field); | 				String description = this.typeUtils.getJavaDoc(field); | ||||||
| 				Object defaultValue = fieldValues.get(name); | 				Object defaultValue = fieldValues.get(name); | ||||||
| 				boolean deprecated = isDeprecated(field) || isDeprecated(element); | 				boolean deprecated = isDeprecated(field) || isDeprecated(element); | ||||||
|  | @ -324,8 +324,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor | ||||||
| 				&& annotation == null && isNested) { | 				&& annotation == null && isNested) { | ||||||
| 			String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); | 			String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name); | ||||||
| 			this.metadataCollector.add(ItemMetadata.newGroup(nestedPrefix, | 			this.metadataCollector.add(ItemMetadata.newGroup(nestedPrefix, | ||||||
| 					this.typeUtils.getType(returnElement), | 					this.typeUtils.getQualifiedName(returnElement), | ||||||
| 					this.typeUtils.getType(element), | 					this.typeUtils.getQualifiedName(element), | ||||||
| 					(getter == null ? null : getter.toString()))); | 					(getter == null ? null : getter.toString()))); | ||||||
| 			processTypeElement(nestedPrefix, (TypeElement) returnElement); | 			processTypeElement(nestedPrefix, (TypeElement) returnElement); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ public class MetadataCollector { | ||||||
| 
 | 
 | ||||||
| 	private void markAsProcessed(Element element) { | 	private void markAsProcessed(Element element) { | ||||||
| 		if (element instanceof TypeElement) { | 		if (element instanceof TypeElement) { | ||||||
| 			this.processedSourceTypes.add(this.typeUtils.getType(element)); | 			this.processedSourceTypes.add(this.typeUtils.getQualifiedName(element)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) { | 	public String getType(TypeMirror type) { | ||||||
| 		if (type == null) { | 		if (type == null) { | ||||||
| 			return null; | 			return null; | ||||||
|  | @ -105,15 +129,23 @@ class TypeUtils { | ||||||
| 		if (wrapper != null) { | 		if (wrapper != null) { | ||||||
| 			return wrapper.getName(); | 			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) { | 		if (type instanceof DeclaredType) { | ||||||
| 			DeclaredType declaredType = (DeclaredType) type; | 			DeclaredType declaredType = (DeclaredType) type; | ||||||
| 			Element enclosingElement = declaredType.asElement().getEnclosingElement(); | 			Element enclosingElement = declaredType.asElement().getEnclosingElement(); | ||||||
| 			if (enclosingElement != null && enclosingElement instanceof TypeElement) { | 			if (enclosingElement != null && enclosingElement instanceof TypeElement) { | ||||||
| 				return getType(enclosingElement) + "$" | 				return (TypeElement) enclosingElement; | ||||||
| 						+ declaredType.asElement().getSimpleName().toString(); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return type.toString(); | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public boolean isCollectionOrMap(TypeMirror type) { | 	public boolean isCollectionOrMap(TypeMirror type) { | ||||||
|  |  | ||||||
|  | @ -58,6 +58,7 @@ import org.springframework.boot.configurationsample.specific.BuilderPojo; | ||||||
| import org.springframework.boot.configurationsample.specific.DeprecatedUnrelatedMethodPojo; | import org.springframework.boot.configurationsample.specific.DeprecatedUnrelatedMethodPojo; | ||||||
| import org.springframework.boot.configurationsample.specific.DoubleRegistrationProperties; | import org.springframework.boot.configurationsample.specific.DoubleRegistrationProperties; | ||||||
| import org.springframework.boot.configurationsample.specific.ExcludedTypesPojo; | 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.InnerClassAnnotatedGetterConfig; | ||||||
| import org.springframework.boot.configurationsample.specific.InnerClassProperties; | import org.springframework.boot.configurationsample.specific.InnerClassProperties; | ||||||
| import org.springframework.boot.configurationsample.specific.InnerClassRootConfig; | import org.springframework.boot.configurationsample.specific.InnerClassRootConfig; | ||||||
|  | @ -361,6 +362,35 @@ public class ConfigurationMetadataAnnotationProcessorTests { | ||||||
| 		compile(InvalidDoubleRegistrationProperties.class); | 		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 | 	@Test | ||||||
| 	public void lombokDataProperties() throws Exception { | 	public void lombokDataProperties() throws Exception { | ||||||
| 		ConfigurationMetadata metadata = compile(LombokSimpleDataProperties.class); | 		ConfigurationMetadata metadata = compile(LombokSimpleDataProperties.class); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,107 @@ | ||||||
|  | /* | ||||||
|  |  * 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; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue