001    /*
002     * Copyright (C) 2007 Google Inc.
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     * http://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    
017    package com.google.common.base;
018    
019    import com.google.common.annotations.GwtCompatible;
020    import com.google.common.annotations.VisibleForTesting;
021    
022    import java.io.Serializable;
023    import java.util.concurrent.TimeUnit;
024    
025    import javax.annotation.Nullable;
026    
027    /**
028     * Useful suppliers.
029     *
030     * <p>All methods return serializable suppliers as long as they're given
031     * serializable parameters.
032     *
033     * @author Laurence Gonsalves
034     * @author Harry Heymann
035     * @since 2 (imported from Google Collections Library)
036     */
037    @GwtCompatible
038    public final class Suppliers {
039      private Suppliers() {}
040    
041      /**
042       * Returns a new supplier which is the composition of the provided function
043       * and supplier. In other words, the new supplier's value will be computed by
044       * retrieving the value from {@code supplier}, and then applying
045       * {@code function} to that value. Note that the resulting supplier will not
046       * call {@code supplier} or invoke {@code function} until it is called.
047       */
048      public static <F, T> Supplier<T> compose(
049          Function<? super F, T> function, Supplier<F> supplier) {
050        Preconditions.checkNotNull(function);
051        Preconditions.checkNotNull(supplier);
052        return new SupplierComposition<F, T>(function, supplier);
053      }
054    
055      private static class SupplierComposition<F, T>
056          implements Supplier<T>, Serializable {
057        final Function<? super F, T> function;
058        final Supplier<F> supplier;
059    
060        SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
061          this.function = function;
062          this.supplier = supplier;
063        }
064        public T get() {
065          return function.apply(supplier.get());
066        }
067        private static final long serialVersionUID = 0;
068      }
069    
070      /**
071       * Returns a supplier which caches the instance retrieved during the first
072       * call to {@code get()} and returns that value on subsequent calls to
073       * {@code get()}. See:
074       * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
075       *
076       * <p>The returned supplier is thread-safe. The supplier's serialized form
077       * does not contain the cached value, which will be recalculated when {@code
078       * get()} is called on the reserialized instance.
079       */
080      public static <T> Supplier<T> memoize(Supplier<T> delegate) {
081        return new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
082      }
083    
084      @VisibleForTesting
085      static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
086        final Supplier<T> delegate;
087        transient boolean initialized;
088        transient T value;
089    
090        MemoizingSupplier(Supplier<T> delegate) {
091          this.delegate = delegate;
092        }
093    
094        public synchronized T get() {
095          if (!initialized) {
096            value = delegate.get();
097            initialized = true;
098          }
099          return value;
100        }
101    
102        private static final long serialVersionUID = 0;
103      }
104    
105      /**
106       * Returns a supplier that caches the instance supplied by the delegate and
107       * removes the cached value after the specified time has passed. Subsequent
108       * calls to {@code get()} return the cached value if the expiration time has
109       * not passed. After the expiration time, a new value is retrieved, cached,
110       * and returned. See:
111       * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
112       *
113       * <p>The returned supplier is thread-safe. The supplier's serialized form
114       * does not contain the cached value, which will be recalculated when {@code
115       * get()} is called on the reserialized instance.
116       *
117       * @param duration the length of time after a value is created that it
118       *     should stop being returned by subsequent {@code get()} calls
119       * @param unit the unit that {@code duration} is expressed in
120       * @throws IllegalArgumentException if {@code duration} is not positive
121       * @since 2
122       */
123      public static <T> Supplier<T> memoizeWithExpiration(
124          Supplier<T> delegate, long duration, TimeUnit unit) {
125        return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
126      }
127    
128      @VisibleForTesting static class ExpiringMemoizingSupplier<T>
129          implements Supplier<T>, Serializable {
130        final Supplier<T> delegate;
131        final long durationNanos;
132        transient boolean initialized;
133        transient T value;
134        transient long expirationNanos;
135    
136        ExpiringMemoizingSupplier(
137            Supplier<T> delegate, long duration, TimeUnit unit) {
138          this.delegate = Preconditions.checkNotNull(delegate);
139          this.durationNanos = unit.toNanos(duration);
140          Preconditions.checkArgument(duration > 0);
141        }
142    
143        public synchronized T get() {
144          if (!initialized || Platform.systemNanoTime() - expirationNanos >= 0) {
145            value = delegate.get();
146            initialized = true;
147            expirationNanos = Platform.systemNanoTime() + durationNanos;
148          }
149          return value;
150        }
151    
152        private static final long serialVersionUID = 0;
153      }
154    
155      /**
156       * Returns a supplier that always supplies {@code instance}.
157       */
158      public static <T> Supplier<T> ofInstance(@Nullable T instance) {
159        return new SupplierOfInstance<T>(instance);
160      }
161    
162      private static class SupplierOfInstance<T>
163          implements Supplier<T>, Serializable {
164        final T instance;
165    
166        SupplierOfInstance(T instance) {
167          this.instance = instance;
168        }
169        public T get() {
170          return instance;
171        }
172        private static final long serialVersionUID = 0;
173      }
174    
175      /**
176       * Returns a supplier whose {@code get()} method synchronizes on
177       * {@code delegate} before calling it, making it thread-safe.
178       */
179      public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
180        return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
181      }
182    
183      private static class ThreadSafeSupplier<T>
184          implements Supplier<T>, Serializable {
185        final Supplier<T> delegate;
186    
187        ThreadSafeSupplier(Supplier<T> delegate) {
188          this.delegate = delegate;
189        }
190        public T get() {
191          synchronized (delegate) {
192            return delegate.get();
193          }
194        }
195        private static final long serialVersionUID = 0;
196      }
197    }