Home / Class/ ParameterPropertyDescriptor Class — spring-boot Architecture

ParameterPropertyDescriptor Class — spring-boot Architecture

Architecture documentation for the ParameterPropertyDescriptor class in ParameterPropertyDescriptor.java from the spring-boot codebase.

Entity Profile

Source Code

configuration-metadata/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ParameterPropertyDescriptor.java lines 39–216

abstract class ParameterPropertyDescriptor extends PropertyDescriptor {

	private final VariableElement parameter;

	ParameterPropertyDescriptor(String name, TypeMirror type, VariableElement parameter, TypeElement declaringElement,
			ExecutableElement getter) {
		super(name, type, declaringElement, getter);
		this.parameter = parameter;

	}

	final VariableElement getParameter() {
		return this.parameter;
	}

	@Override
	protected Object resolveDefaultValue(MetadataGenerationEnvironment environment) {
		Object defaultValue = getDefaultValueFromAnnotation(environment, getParameter());
		return (defaultValue != null) ? defaultValue
				: getParameter().asType().accept(DefaultPrimitiveTypeVisitor.INSTANCE, null);
	}

	private Object getDefaultValueFromAnnotation(MetadataGenerationEnvironment environment, Element element) {
		AnnotationMirror annotation = environment.getDefaultValueAnnotation(element);
		List<String> defaultValue = getDefaultValue(environment, annotation);
		if (defaultValue != null) {
			TypeMirror specificType = determineSpecificType(environment);
			try {
				List<Object> coerced = defaultValue.stream().map((value) -> coerceValue(specificType, value)).toList();
				return (coerced.size() != 1) ? coerced : coerced.get(0);
			}
			catch (IllegalArgumentException ex) {
				environment.getMessager().printMessage(Kind.ERROR, ex.getMessage(), element, annotation);
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	private List<String> getDefaultValue(MetadataGenerationEnvironment environment, AnnotationMirror annotation) {
		if (annotation == null) {
			return null;
		}
		Map<String, Object> values = environment.getAnnotationElementValues(annotation);
		return (List<String>) values.get("value");
	}

	private TypeMirror determineSpecificType(MetadataGenerationEnvironment environment) {
		TypeMirror parameterType = getParameter().asType();
		TypeMirror elementType = environment.getTypeUtils().extractElementType(parameterType);
		parameterType = (elementType != null) ? elementType : parameterType;
		PrimitiveType primitiveType = environment.getTypeUtils().getPrimitiveType(parameterType);
		return (primitiveType != null) ? primitiveType : parameterType;
	}

	private Object coerceValue(TypeMirror type, String value) {
		Object coercedValue = type.accept(DefaultValueCoercionTypeVisitor.INSTANCE, value);
		return (coercedValue != null) ? coercedValue : value;
	}

	@Override
	public boolean isProperty(MetadataGenerationEnvironment env) {
		return !isNested(env); // We must be able to bind it to build the object.
	}

	/**
	 * Visitor that gets the default value for primitives.
	 */
	private static final class DefaultPrimitiveTypeVisitor extends TypeKindVisitor8<Object, Void> {

		static final DefaultPrimitiveTypeVisitor INSTANCE = new DefaultPrimitiveTypeVisitor();

		@Override
		public Object visitPrimitiveAsBoolean(PrimitiveType type, Void parameter) {
			return false;
		}

		@Override
		public Object visitPrimitiveAsByte(PrimitiveType type, Void parameter) {
			return (byte) 0;
		}

		@Override
		public Object visitPrimitiveAsShort(PrimitiveType type, Void parameter) {
			return (short) 0;
		}

		@Override
		public Object visitPrimitiveAsInt(PrimitiveType type, Void parameter) {
			return 0;
		}

		@Override
		public Object visitPrimitiveAsLong(PrimitiveType type, Void parameter) {
			return 0L;
		}

		@Override
		public Object visitPrimitiveAsChar(PrimitiveType type, Void parameter) {
			return null;
		}

		@Override
		public Object visitPrimitiveAsFloat(PrimitiveType type, Void parameter) {
			return 0F;
		}

		@Override
		public Object visitPrimitiveAsDouble(PrimitiveType type, Void parameter) {
			return 0D;
		}

	}

	/**
	 * Visitor that gets the default using coercion.
	 */
	private static final class DefaultValueCoercionTypeVisitor extends TypeKindVisitor8<Object, String> {

		static final DefaultValueCoercionTypeVisitor INSTANCE = new DefaultValueCoercionTypeVisitor();

		private <T extends Number> T parseNumber(String value, Function<String, T> parser,
				PrimitiveType primitiveType) {
			try {
				return parser.apply(value);
			}
			catch (NumberFormatException ex) {
				throw new IllegalArgumentException(
						String.format("Invalid %s representation '%s'", primitiveType, value));
			}
		}

		@Override
		public Object visitPrimitiveAsBoolean(PrimitiveType type, String value) {
			return Boolean.parseBoolean(value);
		}

		@Override
		public Object visitPrimitiveAsByte(PrimitiveType type, String value) {
			return parseNumber(value, Byte::parseByte, type);
		}

		@Override
		public Object visitPrimitiveAsShort(PrimitiveType type, String value) {
			return parseNumber(value, Short::parseShort, type);
		}

		@Override
		public Object visitPrimitiveAsInt(PrimitiveType type, String value) {
			return parseNumber(value, Integer::parseInt, type);
		}

		@Override
		public Object visitPrimitiveAsLong(PrimitiveType type, String value) {
			return parseNumber(value, Long::parseLong, type);
		}

		@Override
		public Object visitPrimitiveAsChar(PrimitiveType type, String value) {
			if (value.length() > 1) {
				throw new IllegalArgumentException(String.format("Invalid character representation '%s'", value));
			}
			return value;
		}

		@Override
		public Object visitPrimitiveAsFloat(PrimitiveType type, String value) {
			return parseNumber(value, Float::parseFloat, type);
		}

		@Override
		public Object visitPrimitiveAsDouble(PrimitiveType type, String value) {
			return parseNumber(value, Double::parseDouble, type);
		}

	}

}

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free