1/*
2 * Copyright (C) 2011 The Guava Authors
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
17package com.google.common.cache;
18
19import static com.google.common.base.Preconditions.checkNotNull;
20
21import com.google.common.annotations.GwtCompatible;
22import com.google.common.base.Function;
23import com.google.common.base.Supplier;
24
25import java.io.Serializable;
26import java.util.Map;
27
28/**
29 * Computes or retrieves values, based on a key, for use in populating a {@code Cache}.
30 *
31 * <p>Most implementations will only need to implement {@link #load}. Other methods may be
32 * overridden as desired.
33 *
34 * @author Charles Fry
35 * @since 10.0
36 */
37@GwtCompatible(emulated = true)
38public abstract class CacheLoader<K, V> {
39  /**
40   * Constructor for use by subclasses.
41   */
42  protected CacheLoader() {}
43
44  /**
45   * Computes or retrieves the value corresponding to {@code key}.
46   *
47   * @param key the non-null key whose value should be loaded
48   * @return the value associated with {@code key}; <b>must not be null</b>
49   */
50  public abstract V load(K key) throws Exception;
51
52  /**
53   * Computes or retrieves the values corresponding to {@code keys}. This method is called by
54   * {@link Cache#getAll}.
55   *
56   * <p>If the returned map doesn't contain all requested {@code keys} then the entries it does
57   * contain will be cached, but {@code getAll} will throw an exception. If the returned map
58   * contains extra keys not present in {@code keys} then all returned entries will be cached,
59   * but only the entries for {@code keys} will be returned from {@code getAll}.
60   *
61   * <p>This method should be overriden when bulk retrieval is significantly more efficient than
62   * many individual lookups. Note that {@link Cache#getAll} will defer to individual calls to
63   * {@link Cache#get} if this method is not overriden.
64   *
65   * @param keys the unique, non-null keys whose values should be loaded
66   * @return a map from each key in {@code keys} to the value associated with that key;
67   *     <b>may not contain null values</b>
68   * @since 11.0
69   */
70  public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
71    // This will be caught by getAll(), causing it to fall back to multiple calls to Cache.get
72    throw new UnsupportedLoadingOperationException();
73  }
74
75  /**
76   * Returns a {@code CacheLoader} which creates values by applying a {@code Function} to the key.
77   */
78  public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
79    return new FunctionToCacheLoader<K, V>(function);
80  }
81
82  private static final class FunctionToCacheLoader<K, V>
83      extends CacheLoader<K, V> implements Serializable {
84    private final Function<K, V> computingFunction;
85
86    public FunctionToCacheLoader(Function<K, V> computingFunction) {
87      this.computingFunction = checkNotNull(computingFunction);
88    }
89
90    @Override
91    public V load(K key) {
92      return computingFunction.apply(key);
93    }
94
95    private static final long serialVersionUID = 0;
96  }
97
98  /**
99   * Returns a {@code CacheLoader} which obtains values from a {@code Supplier} (independent of the
100   * key).
101   */
102  public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
103    return new SupplierToCacheLoader<V>(supplier);
104  }
105
106  private static final class SupplierToCacheLoader<V>
107      extends CacheLoader<Object, V> implements Serializable {
108    private final Supplier<V> computingSupplier;
109
110    public SupplierToCacheLoader(Supplier<V> computingSupplier) {
111      this.computingSupplier = checkNotNull(computingSupplier);
112    }
113
114    @Override
115    public V load(Object key) {
116      return computingSupplier.get();
117    }
118
119    private static final long serialVersionUID = 0;
120  }
121
122  static final class UnsupportedLoadingOperationException extends UnsupportedOperationException {}
123
124  /**
125   * Thrown to indicate that an invalid response was returned from a call to {@link CacheLoader}.
126   *
127   * @since 11.0
128   */
129  public static final class InvalidCacheLoadException extends RuntimeException {
130    public InvalidCacheLoadException(String message) {
131      super(message);
132    }
133  }
134}
135
136