001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.util.function;
018
019import java.util.function.Supplier;
020
021import org.springframework.lang.Nullable;
022import org.springframework.util.Assert;
023
024/**
025 * A {@link java.util.function.Supplier} decorator that caches a singleton result and
026 * makes it available from {@link #get()} (nullable) and {@link #obtain()} (null-safe).
027 *
028 * <p>A {@code SingletonSupplier} can be constructed via {@code of} factory methods
029 * or via constructors that provide a default supplier as a fallback. This is
030 * particularly useful for method reference suppliers, falling back to a default
031 * supplier for a method that returned {@code null} and caching the result.
032 *
033 * @author Juergen Hoeller
034 * @since 5.1
035 * @param <T> the type of results supplied by this supplier
036 */
037public class SingletonSupplier<T> implements Supplier<T> {
038
039        @Nullable
040        private final Supplier<? extends T> instanceSupplier;
041
042        @Nullable
043        private final Supplier<? extends T> defaultSupplier;
044
045        @Nullable
046        private volatile T singletonInstance;
047
048
049        /**
050         * Build a {@code SingletonSupplier} with the given singleton instance
051         * and a default supplier for the case when the instance is {@code null}.
052         * @param instance the singleton instance (potentially {@code null})
053         * @param defaultSupplier the default supplier as a fallback
054         */
055        public SingletonSupplier(@Nullable T instance, Supplier<? extends T> defaultSupplier) {
056                this.instanceSupplier = null;
057                this.defaultSupplier = defaultSupplier;
058                this.singletonInstance = instance;
059        }
060
061        /**
062         * Build a {@code SingletonSupplier} with the given instance supplier
063         * and a default supplier for the case when the instance is {@code null}.
064         * @param instanceSupplier the immediate instance supplier
065         * @param defaultSupplier the default supplier as a fallback
066         */
067        public SingletonSupplier(@Nullable Supplier<? extends T> instanceSupplier, Supplier<? extends T> defaultSupplier) {
068                this.instanceSupplier = instanceSupplier;
069                this.defaultSupplier = defaultSupplier;
070        }
071
072        private SingletonSupplier(Supplier<? extends T> supplier) {
073                this.instanceSupplier = supplier;
074                this.defaultSupplier = null;
075        }
076
077        private SingletonSupplier(T singletonInstance) {
078                this.instanceSupplier = null;
079                this.defaultSupplier = null;
080                this.singletonInstance = singletonInstance;
081        }
082
083
084        /**
085         * Get the shared singleton instance for this supplier.
086         * @return the singleton instance (or {@code null} if none)
087         */
088        @Override
089        @Nullable
090        public T get() {
091                T instance = this.singletonInstance;
092                if (instance == null) {
093                        synchronized (this) {
094                                instance = this.singletonInstance;
095                                if (instance == null) {
096                                        if (this.instanceSupplier != null) {
097                                                instance = this.instanceSupplier.get();
098                                        }
099                                        if (instance == null && this.defaultSupplier != null) {
100                                                instance = this.defaultSupplier.get();
101                                        }
102                                        this.singletonInstance = instance;
103                                }
104                        }
105                }
106                return instance;
107        }
108
109        /**
110         * Obtain the shared singleton instance for this supplier.
111         * @return the singleton instance (never {@code null})
112         * @throws IllegalStateException in case of no instance
113         */
114        public T obtain() {
115                T instance = get();
116                Assert.state(instance != null, "No instance from Supplier");
117                return instance;
118        }
119
120
121        /**
122         * Build a {@code SingletonSupplier} with the given singleton instance.
123         * @param instance the singleton instance (never {@code null})
124         * @return the singleton supplier (never {@code null})
125         */
126        public static <T> SingletonSupplier<T> of(T instance) {
127                return new SingletonSupplier<>(instance);
128        }
129
130        /**
131         * Build a {@code SingletonSupplier} with the given singleton instance.
132         * @param instance the singleton instance (potentially {@code null})
133         * @return the singleton supplier, or {@code null} if the instance was {@code null}
134         */
135        @Nullable
136        public static <T> SingletonSupplier<T> ofNullable(@Nullable T instance) {
137                return (instance != null ? new SingletonSupplier<>(instance) : null);
138        }
139
140        /**
141         * Build a {@code SingletonSupplier} with the given supplier.
142         * @param supplier the instance supplier (never {@code null})
143         * @return the singleton supplier (never {@code null})
144         */
145        public static <T> SingletonSupplier<T> of(Supplier<T> supplier) {
146                return new SingletonSupplier<>(supplier);
147        }
148
149        /**
150         * Build a {@code SingletonSupplier} with the given supplier.
151         * @param supplier the instance supplier (potentially {@code null})
152         * @return the singleton supplier, or {@code null} if the instance supplier was {@code null}
153         */
154        @Nullable
155        public static <T> SingletonSupplier<T> ofNullable(@Nullable Supplier<T> supplier) {
156                return (supplier != null ? new SingletonSupplier<>(supplier) : null);
157        }
158
159}