Home / Class/ Source Class — spring-boot Architecture

Source Class — spring-boot Architecture

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

Entity Profile

Relationship Graph

Source Code

core/spring-boot/src/main/java/org/springframework/boot/context/properties/PropertyMapper.java lines 153–558

	public static final class Source<T> {

		private final Supplier<? extends @Nullable T> supplier;

		private final Predicate<T> predicate;

		private Source(Supplier<? extends @Nullable T> supplier, Predicate<T> predicate) {
			Assert.notNull(predicate, "'predicate' must not be null");
			this.supplier = supplier;
			this.predicate = predicate;
		}

		/**
		 * Return a source that will use the given supplier to obtain a fallback value to
		 * use in place of {@code null}.
		 * @param fallback the fallback supplier
		 * @return a new {@link Source} instance
		 * @since 4.0.0
		 */
		public Source<T> orFrom(Supplier<? extends @Nullable T> fallback) {
			Assert.notNull(fallback, "'fallback' must not be null");
			Supplier<@Nullable T> supplier = () -> {
				T value = getValue();
				return (value != null) ? value : fallback.get();
			};
			return new Source<>(supplier, this.predicate);
		}

		/**
		 * Return an adapted version of the source with {@link Integer} type.
		 * @param <R> the resulting type
		 * @param adapter an adapter to convert the current value to a number.
		 * @return a new adapted source instance
		 */
		public <R extends Number> Source<Integer> asInt(Adapter<? super T, ? extends R> adapter) {
			return as(adapter).as(Number::intValue);
		}

		/**
		 * Return an adapted version of the source changed through the given adapter
		 * function.
		 * @param <R> the resulting type
		 * @param adapter the adapter to apply
		 * @return a new adapted source instance
		 */
		public <R> Source<R> as(Adapter<? super T, ? extends R> adapter) {
			Assert.notNull(adapter, "'adapter' must not be null");
			Supplier<@Nullable R> supplier = () -> {
				T value = getValue();
				return (value != null && this.predicate.test(value)) ? adapter.adapt(value) : null;
			};
			Predicate<R> predicate = (adaptedValue) -> {
				T value = getValue();
				return value != null && this.predicate.test(value);
			};
			return new Source<>(supplier, predicate);
		}

		/**
		 * Return a filtered version of the source that will only map values that are
		 * {@code true}.
		 * @return a new filtered source instance
		 */
		public Source<T> whenTrue() {
			return when(Boolean.TRUE::equals);
		}

		/**
		 * Return a filtered version of the source that will only map values that are
		 * {@code false}.
		 * @return a new filtered source instance
		 */
		public Source<T> whenFalse() {
			return when(Boolean.FALSE::equals);
		}

		/**
		 * Return a filtered version of the source that will only map values that have a
		 * {@code toString()} containing actual text.
		 * @return a new filtered source instance
		 */
		public Source<T> whenHasText() {
			return when((value) -> StringUtils.hasText(value.toString()));
		}

		/**
		 * Return a filtered version of the source that will only map values equal to the
		 * specified {@code object}.
		 * @param object the object to match
		 * @return a new filtered source instance
		 */
		public Source<T> whenEqualTo(@Nullable Object object) {
			return when((value) -> value.equals(object));
		}

		/**
		 * Return a filtered version of the source that will only map values that are an
		 * instance of the given type.
		 * @param <R> the target type
		 * @param target the target type to match
		 * @return a new filtered source instance
		 */
		public <R extends T> Source<R> whenInstanceOf(Class<R> target) {
			Assert.notNull(target, "'target' must not be null");
			return when(target::isInstance).as(target::cast);
		}

		/**
		 * Return a filtered version of the source that won't map values that match the
		 * given predicate.
		 * @param predicate the predicate used to filter values
		 * @return a new filtered source instance
		 */
		public Source<T> whenNot(Predicate<T> predicate) {
			Assert.notNull(predicate, "'predicate' must not be null");
			return when(predicate.negate());
		}

		/**
		 * Return a filtered version of the source that won't map values that don't match
		 * the given predicate.
		 * @param predicate the predicate used to filter values
		 * @return a new filtered source instance
		 */
		public Source<T> when(Predicate<T> predicate) {
			Assert.notNull(predicate, "'predicate' must not be null");
			return new Source<>(this.supplier, this.predicate.and(predicate));
		}

		/**
		 * Complete the mapping by passing any non-filtered value to the specified
		 * consumer. The method is designed to be used with mutable objects.
		 * @param consumer the consumer that should accept the value if it's not been
		 * filtered
		 */
		public void to(Consumer<? super T> consumer) {
			Assert.notNull(consumer, "'consumer' must not be null");
			T value = getValue();
			if (value != null && test(value)) {
				consumer.accept(value);
			}
		}

		/**
		 * Complete the mapping for any non-filtered value by applying the given function
		 * to an existing instance and returning a new one. For filtered values, the
		 * {@code instance} parameter is returned unchanged. The method is designed to be
		 * used with immutable objects.
		 * @param <R> the result type
		 * @param instance the current instance
		 * @param mapper the mapping function
		 * @return a new mapped instance or the original instance
		 * @since 3.0.0
		 */
		public <R> R to(R instance, BiFunction<R, ? super T, R> mapper) {
			Assert.notNull(instance, "'instance' must not be null");
			Assert.notNull(mapper, "'mapper' must not be null");
			T value = getValue();
			if (value != null && test(value)) {
				return mapper.apply(instance, value);
			}
			return instance;
		}

		/**
		 * Complete the mapping by creating a new instance from the non-filtered value.
		 * @param <R> the resulting type
		 * @param factory the factory used to create the instance
		 * @return the instance
		 * @throws NoSuchElementException if the value has been filtered
		 */
		public <R> R toInstance(Function<? super T, R> factory) {
			Assert.notNull(factory, "'factory' must not be null");
			T value = getValue();
			if (value != null && test(value)) {
				return factory.apply(value);
			}
			throw new NoSuchElementException("No value present");
		}

		/**
		 * Complete the mapping by calling the specified method when the value has not
		 * been filtered.
		 * @param runnable the method to call if the value has not been filtered
		 */
		public void toCall(Runnable runnable) {
			Assert.notNull(runnable, "'runnable' must not be null");
			T value = getValue();
			if (value != null && test(value)) {
				runnable.run();
			}
		}

		/**
		 * Return a version of this source that can be used to always complete mappings,
		 * even if values are {@code null}.
		 * @return a new {@link Always} instance
		 * @since 4.0.0
		 */
		public Always<T> always() {
			Supplier<@Nullable T> getValue = this::getValue;
			return new Always<>(getValue, this::test);
		}

		private @Nullable T getValue() {
			try {
				return this.supplier.get();
			}
			catch (NullPointerException ex) {
				return null;
			}
		}

		private boolean test(T value) {
			Assert.state(value != null, "'value' must not be null");
			return this.predicate.test(value);
		}

		/**
		 * Adapter used to adapt a value and possibly return a {@code null} result.
		 *
		 * @param <T> the source type
		 * @param <R> the result type
		 * @since 4.0.0
		 */
		@FunctionalInterface
		public interface Adapter<T, R> {

			/**
			 * Adapt the given value.
			 * @param value the value to adapt
			 * @return an adapted value or {@code null}
			 */
			@Nullable R adapt(T value);

		}

		/**
		 * Allow source mapping to complete using methods that accept nulls.
		 *
		 * @param <T> the source type
		 * @since 4.0.0
		 */
		public static class Always<T> {

			private final Supplier<@Nullable T> supplier;

			private final Predicate<T> predicate;

			Always(Supplier<@Nullable T> supplier, Predicate<T> predicate) {
				this.supplier = supplier;
				this.predicate = predicate;
			}

			/**
			 * Return an adapted version of the source changed through the given adapter
			 * function.
			 * @param <R> the resulting type
			 * @param adapter the adapter to apply
			 * @return a new adapted source instance
			 */
			public <R> Always<R> as(Adapter<? super T, ? extends R> adapter) {
				Assert.notNull(adapter, "'adapter' must not be null");
				Supplier<@Nullable R> supplier = () -> {
					T value = getValue();
					return (value == null || test(value)) ? adapter.adapt(value) : null;
				};
				Predicate<R> predicate = (adaptedValue) -> {
					T value = getValue();
					return value == null || test(value);
				};
				return new Always<>(supplier, predicate);
			}

			/**
			 * Complete the mapping by passing any non-filtered value to the specified
			 * consumer. The method is designed to be used with mutable objects.
			 * @param consumer the consumer that should accept the value if it's not been
			 * filtered
			 */
			public void to(Consumer<@Nullable ? super T> consumer) {
				Assert.notNull(consumer, "'consumer' must not be null");
				T value = getValue();
				if (value == null || test(value)) {
					consumer.accept(value);
				}
			}

			/**
			 * Complete the mapping for any non-filtered value by applying the given
			 * function to an existing instance and returning a new one. For filtered
			 * values, the {@code instance} parameter is returned unchanged. The method is
			 * designed to be used with immutable objects.
			 * @param <R> the result type
			 * @param instance the current instance
			 * @param mapper the mapping function
			 * @return a new mapped instance or the original instance
			 */
			public <R> R to(R instance, Mapper<R, ? super T> mapper) {
				Assert.notNull(instance, "'instance' must not be null");
				Assert.notNull(mapper, "'mapper' must not be null");
				T value = getValue();
				if (value == null || test(value)) {
					return mapper.map(instance, value);
				}
				return instance;
			}

			/**
			 * Complete the mapping by creating a new instance from the non-filtered
			 * value.
			 * @param <R> the resulting type
			 * @param factory the factory used to create the instance
			 * @return the instance
			 * @throws NoSuchElementException if the value has been filtered
			 */
			public <R> R toInstance(Factory<? super T, ? extends R> factory) {
				Assert.notNull(factory, "'factory' must not be null");
				T value = getValue();
				if (value == null || test(value)) {
					return factory.create(value);
				}
				throw new NoSuchElementException("No value present");
			}

			/**
			 * Complete the mapping by calling the specified method when the value has not
			 * been filtered.
			 * @param runnable the method to call if the value has not been filtered
			 */
			public void toCall(Runnable runnable) {
				Assert.notNull(runnable, "'runnable' must not be null");
				T value = getValue();
				if (value == null || test(value)) {
					runnable.run();
				}
			}

			private @Nullable T getValue() {
				return this.supplier.get();
			}

			private boolean test(T value) {
				Assert.state(value != null, "'value' must not be null");
				return this.predicate.test(value);
			}

			/**
			 * Adapter that support nullable values.
			 *
			 * @param <T> the source type
			 * @param <R> the result type
			 */
			@FunctionalInterface
			public interface Adapter<T, R> {

				/**
				 * Adapt the given value.
				 * @param value the value to adapt
				 * @return an adapted value or {@code null}
				 */
				@Nullable R adapt(@Nullable T value);

			}

			/**
			 * Factory that supports nullable values.
			 *
			 * @param <T> the source type
			 * @param <R> the result type
			 */
			@FunctionalInterface
			public interface Factory<T, R extends @Nullable Object> {

				/**
				 * Create a new instance for the given nullable value.
				 * @param value the value used to create the instance (may be
				 * {@code null})
				 * @return the resulting instance
				 */
				R create(@Nullable T value);

			}

			/**
			 * Mapper that supports nullable values.
			 *
			 * @param <T> the source type
			 * @param <R> the result type
			 */
			@FunctionalInterface
			public interface Mapper<R extends @Nullable Object, T> {

				/**
				 * Map a existing instance for the given nullable value.
				 * @param instance the existing instance
				 * @param value the value to map (may be {@code null})
				 * @return the resulting mapped instance
				 */
				R map(R instance, @Nullable T value);

			}

		}

	}

Domain

Analyze Your Own Codebase

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

Try Supermodel Free