001/*
002 * Copyright 2002-2019 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.cache;
018
019import java.util.concurrent.Callable;
020
021import org.springframework.lang.Nullable;
022
023/**
024 * Interface that defines common cache operations.
025 *
026 * <b>Note:</b> Due to the generic use of caching, it is recommended that
027 * implementations allow storage of <tt>null</tt> values (for example to
028 * cache methods that return {@code null}).
029 *
030 * @author Costin Leau
031 * @author Juergen Hoeller
032 * @author Stephane Nicoll
033 * @since 3.1
034 */
035public interface Cache {
036
037        /**
038         * Return the cache name.
039         */
040        String getName();
041
042        /**
043         * Return the underlying native cache provider.
044         */
045        Object getNativeCache();
046
047        /**
048         * Return the value to which this cache maps the specified key.
049         * <p>Returns {@code null} if the cache contains no mapping for this key;
050         * otherwise, the cached value (which may be {@code null} itself) will
051         * be returned in a {@link ValueWrapper}.
052         * @param key the key whose associated value is to be returned
053         * @return the value to which this cache maps the specified key,
054         * contained within a {@link ValueWrapper} which may also hold
055         * a cached {@code null} value. A straight {@code null} being
056         * returned means that the cache contains no mapping for this key.
057         * @see #get(Object, Class)
058         * @see #get(Object, Callable)
059         */
060        @Nullable
061        ValueWrapper get(Object key);
062
063        /**
064         * Return the value to which this cache maps the specified key,
065         * generically specifying a type that return value will be cast to.
066         * <p>Note: This variant of {@code get} does not allow for differentiating
067         * between a cached {@code null} value and no cache entry found at all.
068         * Use the standard {@link #get(Object)} variant for that purpose instead.
069         * @param key the key whose associated value is to be returned
070         * @param type the required type of the returned value (may be
071         * {@code null} to bypass a type check; in case of a {@code null}
072         * value found in the cache, the specified type is irrelevant)
073         * @return the value to which this cache maps the specified key
074         * (which may be {@code null} itself), or also {@code null} if
075         * the cache contains no mapping for this key
076         * @throws IllegalStateException if a cache entry has been found
077         * but failed to match the specified type
078         * @since 4.0
079         * @see #get(Object)
080         */
081        @Nullable
082        <T> T get(Object key, @Nullable Class<T> type);
083
084        /**
085         * Return the value to which this cache maps the specified key, obtaining
086         * that value from {@code valueLoader} if necessary. This method provides
087         * a simple substitute for the conventional "if cached, return; otherwise
088         * create, cache and return" pattern.
089         * <p>If possible, implementations should ensure that the loading operation
090         * is synchronized so that the specified {@code valueLoader} is only called
091         * once in case of concurrent access on the same key.
092         * <p>If the {@code valueLoader} throws an exception, it is wrapped in
093         * a {@link ValueRetrievalException}
094         * @param key the key whose associated value is to be returned
095         * @return the value to which this cache maps the specified key
096         * @throws ValueRetrievalException if the {@code valueLoader} throws an exception
097         * @since 4.3
098         * @see #get(Object)
099         */
100        @Nullable
101        <T> T get(Object key, Callable<T> valueLoader);
102
103        /**
104         * Associate the specified value with the specified key in this cache.
105         * <p>If the cache previously contained a mapping for this key, the old
106         * value is replaced by the specified value.
107         * <p>Actual registration may be performed in an asynchronous or deferred
108         * fashion, with subsequent lookups possibly not seeing the entry yet.
109         * This may for example be the case with transactional cache decorators.
110         * Use {@link #putIfAbsent} for guaranteed immediate registration.
111         * @param key the key with which the specified value is to be associated
112         * @param value the value to be associated with the specified key
113         * @see #putIfAbsent(Object, Object)
114         */
115        void put(Object key, @Nullable Object value);
116
117        /**
118         * Atomically associate the specified value with the specified key in this cache
119         * if it is not set already.
120         * <p>This is equivalent to:
121         * <pre><code>
122         * ValueWrapper existingValue = cache.get(key);
123         * if (existingValue == null) {
124         *     cache.put(key, value);
125         * }
126         * return existingValue;
127         * </code></pre>
128         * except that the action is performed atomically. While all out-of-the-box
129         * {@link CacheManager} implementations are able to perform the put atomically,
130         * the operation may also be implemented in two steps, e.g. with a check for
131         * presence and a subsequent put, in a non-atomic way. Check the documentation
132         * of the native cache implementation that you are using for more details.
133         * <p>The default implementation delegates to {@link #get(Object)} and
134         * {@link #put(Object, Object)} along the lines of the code snippet above.
135         * @param key the key with which the specified value is to be associated
136         * @param value the value to be associated with the specified key
137         * @return the value to which this cache maps the specified key (which may be
138         * {@code null} itself), or also {@code null} if the cache did not contain any
139         * mapping for that key prior to this call. Returning {@code null} is therefore
140         * an indicator that the given {@code value} has been associated with the key.
141         * @since 4.1
142         * @see #put(Object, Object)
143         */
144        @Nullable
145        default ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
146                ValueWrapper existingValue = get(key);
147                if (existingValue == null) {
148                        put(key, value);
149                }
150                return existingValue;
151        }
152
153        /**
154         * Evict the mapping for this key from this cache if it is present.
155         * <p>Actual eviction may be performed in an asynchronous or deferred
156         * fashion, with subsequent lookups possibly still seeing the entry.
157         * This may for example be the case with transactional cache decorators.
158         * Use {@link #evictIfPresent} for guaranteed immediate removal.
159         * @param key the key whose mapping is to be removed from the cache
160         * @see #evictIfPresent(Object)
161         */
162        void evict(Object key);
163
164        /**
165         * Evict the mapping for this key from this cache if it is present,
166         * expecting the key to be immediately invisible for subsequent lookups.
167         * <p>The default implementation delegates to {@link #evict(Object)},
168         * returning {@code false} for not-determined prior presence of the key.
169         * Cache providers and in particular cache decorators are encouraged
170         * to perform immediate eviction if possible (e.g. in case of generally
171         * deferred cache operations within a transaction) and to reliably
172         * determine prior presence of the given key.
173         * @param key the key whose mapping is to be removed from the cache
174         * @return {@code true} if the cache was known to have a mapping for
175         * this key before, {@code false} if it did not (or if prior presence
176         * could not be determined)
177         * @since 5.2
178         * @see #evict(Object)
179         */
180        default boolean evictIfPresent(Object key) {
181                evict(key);
182                return false;
183        }
184
185        /**
186         * Clear the cache through removing all mappings.
187         * <p>Actual clearing may be performed in an asynchronous or deferred
188         * fashion, with subsequent lookups possibly still seeing the entries.
189         * This may for example be the case with transactional cache decorators.
190         * Use {@link #invalidate()} for guaranteed immediate removal of entries.
191         * @see #invalidate()
192         */
193        void clear();
194
195        /**
196         * Invalidate the cache through removing all mappings, expecting all
197         * entries to be immediately invisible for subsequent lookups.
198         * @return {@code true} if the cache was known to have mappings before,
199         * {@code false} if it did not (or if prior presence of entries could
200         * not be determined)
201         * @since 5.2
202         * @see #clear()
203         */
204        default boolean invalidate() {
205                clear();
206                return false;
207        }
208
209
210        /**
211         * A (wrapper) object representing a cache value.
212         */
213        @FunctionalInterface
214        interface ValueWrapper {
215
216                /**
217                 * Return the actual value in the cache.
218                 */
219                @Nullable
220                Object get();
221        }
222
223
224        /**
225         * Wrapper exception to be thrown from {@link #get(Object, Callable)}
226         * in case of the value loader callback failing with an exception.
227         * @since 4.3
228         */
229        @SuppressWarnings("serial")
230        class ValueRetrievalException extends RuntimeException {
231
232                @Nullable
233                private final Object key;
234
235                public ValueRetrievalException(@Nullable Object key, Callable<?> loader, Throwable ex) {
236                        super(String.format("Value for key '%s' could not be loaded using '%s'", key, loader), ex);
237                        this.key = key;
238                }
239
240                @Nullable
241                public Object getKey() {
242                        return this.key;
243                }
244        }
245
246}