001    /*
002     * Copyright (C) 2011 The Guava 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     * 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.cache;
018    
019    import com.google.common.annotations.Beta;
020    import com.google.common.annotations.GwtCompatible;
021    import com.google.common.base.Function;
022    import com.google.common.collect.ImmutableMap;
023    import com.google.common.util.concurrent.ExecutionError;
024    import com.google.common.util.concurrent.UncheckedExecutionException;
025    
026    import java.util.concurrent.ExecutionException;
027    
028    /**
029     * A semi-persistent mapping from keys to values. Values are automatically loaded by the cache,
030     * and are stored in the cache until either evicted or manually invalidated.
031     *
032     * <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
033     * by multiple concurrent threads.
034     *
035     * <p>All methods other than {@link #get} and {@link #getUnchecked} are optional.
036     *
037     * <p>When evaluated as a {@link Function}, a cache yields the same result as invoking
038     * {@link #getUnchecked}.
039     *
040     * @author Charles Fry
041     * @since 11.0
042     */
043    @Beta
044    @GwtCompatible
045    public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
046    
047      /**
048       * Returns the value associated with {@code key} in this cache, first loading that value if
049       * necessary. No observable state associated with this cache is modified until loading completes.
050       *
051       * <p>If another call to {@link #get} or {@link #getUnchecked} is currently loading the value for
052       * {@code key}, simply waits for that thread to finish and returns its loaded value. Note that
053       * multiple threads can concurrently load values for distinct keys.
054       *
055       * <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#load} to load new values
056       * into the cache. Newly loaded values are added to the cache using
057       * {@code Cache.asMap().putIfAbsent} after loading has completed; if another value was associated
058       * with {@code key} while the new value was loading then a removal notification will be sent for
059       * the new value.
060       *
061       * <p>If the cache loader associated with this cache is known not to throw checked
062       * exceptions, then prefer {@link #getUnchecked} over this method.
063       *
064       * @throws ExecutionException if a checked exception was thrown while loading the value
065       * @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
066       *     value
067       * @throws ExecutionError if an error was thrown while loading the value
068       */
069      V get(K key) throws ExecutionException;
070    
071      /**
072       * Returns the value associated with {@code key} in this cache, first loading that value if
073       * necessary. No observable state associated with this cache is modified until loading
074       * completes. Unlike {@link #get}, this method does not throw a checked exception, and thus should
075       * only be used in situations where checked exceptions are not thrown by the cache loader.
076       *
077       * <p>If another call to {@link #get} or {@link #getUnchecked} is currently loading the value for
078       * {@code key}, simply waits for that thread to finish and returns its loaded value. Note that
079       * multiple threads can concurrently load values for distinct keys.
080       *
081       * <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#load} to load new values
082       * into the cache. Newly loaded values are added to the cache using
083       * {@code Cache.asMap().putIfAbsent} after loading has completed; if another value was associated
084       * with {@code key} while the new value was loading then a removal notification will be sent for
085       * the new value.
086       *
087       * <p><b>Warning:</b> this method silently converts checked exceptions to unchecked exceptions,
088       * and should not be used with cache loaders which throw checked exceptions. In such cases use
089       * {@link #get} instead.
090       *
091       * @throws UncheckedExecutionException if an exception was thrown while loading the value,
092       *     regardless of whether the exception was checked or unchecked
093       * @throws ExecutionError if an error was thrown while loading the value
094       */
095      V getUnchecked(K key);
096    
097      /**
098       * Returns a map of the values associated with {@code keys}, creating or retrieving those values
099       * if necessary. The returned map contains entries that were already cached, combined with newly
100       * loaded entries; it will never contain null keys or values.
101       *
102       * <p>Caches loaded by a {@link CacheLoader} will issue a single request to
103       * {@link CacheLoader#loadAll} for all keys which are not already present in the cache. All
104       * entries returned by {@link CacheLoader#loadAll} will be stored in the cache, over-writing
105       * any previously cached values. This method will throw an exception if
106       * {@link CacheLoader#loadAll} returns {@code null}, returns a map containing null keys or values,
107       * or fails to return an entry for each requested key.
108       *
109       * <p>Note that duplicate elements in {@code keys}, as determined by {@link Object#equals}, will
110       * be ignored.
111       *
112       * @throws ExecutionException if a checked exception was thrown while loading the values
113       * @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
114       *     values
115       * @throws ExecutionError if an error was thrown while loading the values
116       * @since 11.0
117       */
118      ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException;
119    
120      /**
121       * Discouraged. Provided to satisfy the {@code Function} interface; use {@link #get} or
122       * {@link #getUnchecked} instead.
123       *
124       * @throws UncheckedExecutionException if an exception was thrown while loading the value,
125       *     regardless of whether the exception was checked or unchecked
126       * @throws ExecutionError if an error was thrown while loading the value
127       */
128      @Override
129      V apply(K key);
130    
131      /**
132       * Loads a new value for key {@code key}, possibly asynchronously. While the new value is loading
133       * the previous value (if any) will continue to be returned by {@code get(key)} unless it is
134       * evicted. If the new value is loaded successfully it will replace the previous value in the
135       * cache; if an exception is thrown while refreshing the previous value will remain, <i>and the
136       * exception will be logged (using {@link java.util.logging.Logger}) and swallowed</i>.
137       *
138       * <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#reload} if the
139       * cache currently contains a value for {@code key}, and {@link CacheLoader#load} otherwise.
140       *
141       * <p>Returns without doing anything if another thread is currently loading the value for
142       * {@code key}. If the cache loader associated with this cache performs refresh asynchronously
143       * then this method may return before refresh completes.
144       *
145       * @since 11.0
146       */
147      void refresh(K key);
148    }