1 package com.atlassian.vcache;
2
3 import com.atlassian.annotations.PublicApi;
4
5 import java.util.Arrays;
6 import java.util.Map;
7 import java.util.Optional;
8 import java.util.Set;
9 import java.util.function.Function;
10 import java.util.function.Supplier;
11
12 /**
13 * Represents the common operations that can be performed on a JVM local cache.
14 *
15 * @param <K> the key type
16 * @param <V> the value type
17 * @since 1.0
18 */
19 @PublicApi
20 public interface LocalCacheOperations<K, V> {
21 /**
22 * Returns a value that is associated with a specified key.
23 *
24 * @param key the key to check.
25 * @return an {@link Optional} which may contain the value associated with the key.
26 */
27 Optional<V> get(K key);
28
29 /**
30 * Returns a value that may be associated with a specified key.
31 * <p>Notes:</p>
32 * <ul>
33 * <li>
34 * If no entry for the specified key exists, then the specified <tt>supplier</tt> is called to create
35 * an entry in the cache, before it is returned.
36 * </li>
37 * <li>
38 * The <tt>supplier</tt> implementation needs to be multi-thread safe as it may be called concurrently
39 * if multiple threads call this method.
40 * </li>
41 * </ul>
42 *
43 * @param key the key uniquely identifying the value to be retrieved
44 * @param supplier used to generate the value, if one does not exist already for the key. The supplier may not
45 * return {@code null}.
46 * @return the value associated with the key.
47 */
48 V get(K key, Supplier<? extends V> supplier);
49
50 /**
51 * Returns the values that are associated with the specified keys. It is equivalent to calling
52 * {@link #getBulk(Function, Iterable)} passing {@code factory} and {@code Arrays.asList(keys)} as the parameters.
53 *
54 * @param factory used to generate the values for the keys that do not have entries. The factory must return a
55 * map containing only a non-null value for each supplied key. Extra keys are not allowed.
56 * @param keys the keys to retrieve
57 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
58 * the value associated with the key.
59 * @see #getBulk(Function, Iterable)
60 */
61 @SuppressWarnings("unchecked")
62 default Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, K... keys) {
63 return getBulk(factory, Arrays.asList(keys));
64 }
65
66 /**
67 * Returns the values that are associated with the specified keys.
68 * <p>Notes:</p>
69 * <ul>
70 * <li>
71 * <b>WARNING:</b> this method is not multi-thread safe in conjunction with any methods that make single key
72 * mutations, such as {@link #remove(Object)} or {@link #removeIf(Object, Object)}. Caller beware.
73 * </li>
74 * <li>
75 * If there are any keys for which no entry exists, then the given <tt>factory</tt> is called exactly once with
76 * the argument being a <tt>Set</tt> containing exactly the keys for which no entry existed.
77 * The return value of the <tt>factory</tt> is used to populate the missing entries in the cache,
78 * and then the map of all requested keys to values is returned.
79 * </li>
80 * <li>
81 * The call to the factory is made on the thread which calls <tt>getBulk</tt>.
82 * </li>
83 * <li>
84 * Despite the fact that the keys are an <tt>Iterable</tt>, no guarantees are made about the order in which
85 * the cache is populated, nor the order in which the <tt>Set</tt> passed to the factory is iterated,
86 * nor in which the returned <tt>Map</tt> is iterated.
87 * </li>
88 * </ul>
89 *
90 * @param factory used to generate the values for the keys that do not have entries. The factory must return a
91 * map containing only a non-null value for each supplied key. Extra keys are not allowed.
92 * @param keys the keys to retrieve
93 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
94 * the value associated with the key.
95 */
96 Map<K, V> getBulk(Function<Set<K>, Map<K, V>> factory, Iterable<K> keys);
97
98 /**
99 * Unconditionally puts the value under the specified key.
100 *
101 * @param key the key to put the data under
102 * @param value the value to associate with the key.
103 */
104 void put(K key, V value);
105
106 /**
107 * Conditionally puts the value under the specified key, if no entry currently exists. Returns the current
108 * value associated with the key, if one currently exists.
109 *
110 * @param key the key to put the data under
111 * @param value the value to associate with the key.
112 * @return {@link Optional#EMPTY} is no entry previously existed, otherwise the {@link Optional} contains
113 * the current value.
114 */
115 Optional<V> putIfAbsent(K key, V value);
116
117 /**
118 * Conditionally replaces the value associated with a key, iff:
119 * <ul>
120 * <li>An entry already exists for the key</li>
121 * <li>The current value matches the supplied <tt>currentValue</tt> using {@link Object#equals(Object)}</li>
122 * </ul>
123 *
124 * @param key the key to replace data under
125 * @param currentValue the current value to match
126 * @param newValue the replacement value
127 * @return whether the current value are replaced with the supplied <tt>newValue</tt>
128 */
129 boolean replaceIf(K key, V currentValue, V newValue);
130
131 /**
132 * Conditionally removed an entry for a specified key, iff:
133 * <ul>
134 * <li>An entry already exists for the key</li>
135 * <li>The current value matches the supplied <tt>value</tt> using {@link Object#equals(Object)}</li>
136 * </ul>
137 *
138 * @param key the key of the entry to remove conditionally
139 * @param value the current value to match
140 * @return whether an entry was removed
141 */
142 boolean removeIf(K key, V value);
143
144 /**
145 * Removes the entries for the supplied key.
146 *
147 * @param key the key of the entry to remove
148 */
149 void remove(K key);
150
151 /**
152 * Removes all the entries in the cache.
153 */
154 void removeAll();
155 }