1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.base; 18 19 import com.google.common.annotations.VisibleForTesting; 20 21 import java.io.Serializable; 22 import java.util.concurrent.TimeUnit; 23 24 import javax.annotation.Nullable; 25 26 /** 27 * Useful suppliers. 28 * 29 * <p>All methods return serializable suppliers as long as they're given 30 * serializable parameters. 31 * 32 * @author Laurence Gonsalves 33 * @author Harry Heymann 34 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library) 35 */ 36 public final class Suppliers { 37 private Suppliers() {} 38 39 /** 40 * Returns a new supplier which is the composition of the provided function 41 * and supplier. In other words, the new supplier's value will be computed by 42 * retrieving the value from {@code first}, and then applying 43 * {@code function} to that value. Note that the resulting supplier will not 44 * call {@code first} or invoke {@code function} until it is called. 45 */ 46 public static <F, T> Supplier<T> compose( 47 Function<? super F, T> function, Supplier<F> first) { 48 Preconditions.checkNotNull(function); 49 Preconditions.checkNotNull(first); 50 return new SupplierComposition<F, T>(function, first); 51 } 52 53 private static class SupplierComposition<F, T> 54 implements Supplier<T>, Serializable { 55 final Function<? super F, ? extends T> function; 56 final Supplier<? extends F> first; 57 58 SupplierComposition(Function<? super F, ? extends T> function, 59 Supplier<? extends F> first) { 60 this.function = function; 61 this.first = first; 62 } 63 public T get() { 64 return function.apply(first.get()); 65 } 66 private static final long serialVersionUID = 0; 67 } 68 69 /** 70 * Returns a supplier which caches the instance retrieved during the first 71 * call to {@code get()} and returns that value on subsequent calls to 72 * {@code get()}. See: 73 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 74 * 75 * <p>The returned supplier is thread-safe. The supplier's serialized form 76 * does not contain the cached value, which will be recalculated when {@code 77 * get()} is called on the reserialized instance. 78 */ 79 public static <T> Supplier<T> memoize(Supplier<T> delegate) { 80 return new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate)); 81 } 82 83 @VisibleForTesting static class MemoizingSupplier<T> 84 implements Supplier<T>, Serializable { 85 final Supplier<T> delegate; 86 transient boolean initialized; 87 transient T value; 88 89 MemoizingSupplier(Supplier<T> delegate) { 90 this.delegate = delegate; 91 } 92 93 public synchronized T get() { 94 if (!initialized) { 95 value = delegate.get(); 96 initialized = true; 97 } 98 return value; 99 } 100 101 private static final long serialVersionUID = 0; 102 } 103 104 /** 105 * Returns a supplier that caches the instance supplied by the delegate and 106 * removes the cached value after the specified time has passed. Subsequent 107 * calls to {@code get()} return the cached value if the expiration time has 108 * not passed. After the expiration time, a new value is retrieved, cached, 109 * and returned. See: 110 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 111 * 112 * <p>The returned supplier is thread-safe. The supplier's serialized form 113 * does not contain the cached value, which will be recalculated when {@code 114 * get()} is called on the reserialized instance. 115 * 116 * @param duration the length of time after a value is created that it 117 * should stop being returned by subsequent {@code get()} calls 118 * @param unit the unit that {@code duration} is expressed in 119 * @throws IllegalArgumentException if {@code duration} is not positive 120 * @since 2010.01.04 <b>tentative</b> 121 */ 122 public static <T> Supplier<T> memoizeWithExpiration( 123 Supplier<T> delegate, long duration, TimeUnit unit) { 124 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 125 } 126 127 @VisibleForTesting static class ExpiringMemoizingSupplier<T> 128 implements Supplier<T>, Serializable { 129 final Supplier<T> delegate; 130 final long durationNanos; 131 transient boolean initialized; 132 transient T value; 133 transient long expirationNanos; 134 135 ExpiringMemoizingSupplier( 136 Supplier<T> delegate, long duration, TimeUnit unit) { 137 this.delegate = Preconditions.checkNotNull(delegate); 138 this.durationNanos = unit.toNanos(duration); 139 Preconditions.checkArgument(duration > 0); 140 } 141 142 public synchronized T get() { 143 if (!initialized || System.nanoTime() - expirationNanos >= 0) { 144 value = delegate.get(); 145 initialized = true; 146 expirationNanos = System.nanoTime() + durationNanos; 147 } 148 return value; 149 } 150 151 private static final long serialVersionUID = 0; 152 } 153 154 /** 155 * Returns a supplier that always supplies {@code instance}. 156 */ 157 public static <T> Supplier<T> ofInstance(@Nullable T instance) { 158 return new SupplierOfInstance<T>(instance); 159 } 160 161 private static class SupplierOfInstance<T> 162 implements Supplier<T>, Serializable { 163 final T instance; 164 165 SupplierOfInstance(T instance) { 166 this.instance = instance; 167 } 168 public T get() { 169 return instance; 170 } 171 private static final long serialVersionUID = 0; 172 } 173 174 /** 175 * Returns a supplier whose {@code get()} method synchronizes on 176 * {@code delegate} before calling it, making it thread-safe. 177 */ 178 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) { 179 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate)); 180 } 181 182 private static class ThreadSafeSupplier<T> 183 implements Supplier<T>, Serializable { 184 final Supplier<T> delegate; 185 186 ThreadSafeSupplier(Supplier<T> delegate) { 187 this.delegate = delegate; 188 } 189 public T get() { 190 synchronized (delegate) { 191 return delegate.get(); 192 } 193 } 194 private static final long serialVersionUID = 0; 195 } 196 } 197