1 package com.atlassian.vcache;
2
3 import java.util.Arrays;
4 import java.util.Collection;
5 import java.util.Map;
6 import java.util.Optional;
7 import java.util.function.Function;
8 import java.util.function.Supplier;
9 import javax.annotation.Nonnull;
10
11 import com.atlassian.annotations.PublicApi;
12
13 /**
14 * Represents the common operations that can be performed on a JVM local cache.
15 *
16 * @param <K> the key type
17 * @param <V> the value type
18 *
19 * @since 1.0
20 */
21 @PublicApi
22 public interface LocalCacheOperations<K, V>
23 {
24 /**
25 * Returns a value that is associated with a specified key.
26 *
27 * @param key the key to check.
28 * @return an {@link Optional} which may contain the value associated with the key.
29 */
30 @Nonnull
31 Optional<V> get(K key);
32
33 /**
34 * Returns a value that may be associated with a specified key.
35 * <p>Notes:</p>
36 * <ul>
37 * <li>
38 * If no entry for the specified key exists, then the specified <tt>supplier</tt> is called to create
39 * an entry in the cache, before it is returned.
40 * </li>
41 * <li>
42 * The <tt>supplier</tt> implementation needs to be multi-thread safe as it may be called concurrently
43 * if multiple threads call this method.
44 * </li>
45 * </ul>
46 *
47 * @param key the key uniquely identifying the value to be retrieved
48 * @param supplier used to generate the value, if one does not exist already for the key. The supplier may not
49 * return {@code null}.
50 * @return the value associated with the key.
51 */
52 @Nonnull
53 V get(K key, Supplier<? extends V> supplier);
54
55 /**
56 * Unconditionally puts the value under the specified key, and returns the previous value associated
57 * with the key (if one existed).
58 *
59 * @param key the key to put the data under
60 * @param value the value to associate with the key.
61 * @return an {@link Optional} which may contain the previous value associated with the key.
62 */
63 @Nonnull
64 Optional<V> put(K key, V value);
65
66 /**
67 * Conditionally puts the value under the specified key, if no entry currently exists. Returns the current
68 * value associated with the key, if one currently exists.
69 *
70 * @param key the key to put the data under
71 * @param value the value to associate with the key.
72 * @return {@link Optional#EMPTY} is no entry previously existed, otherwise the {@link Optional} contains
73 * the current value.
74 */
75 @Nonnull
76 Optional<V> putIfAbsent(K key, V value);
77
78 /**
79 * Conditionally replaces the value associated with a key, iff:
80 * <ul>
81 * <li>An entry already exists for the key</li>
82 * <li>The current value matches the supplied <tt>currentValue</tt> using {@link Object#equals(Object)}</li>
83 * </ul>
84 *
85 * @param key the key to replace data under
86 * @param currentValue the current value to match
87 * @param newValue the replacement value
88 * @return whether the current value are replaced with the supplied <tt>newValue</tt>
89 */
90 boolean replaceIf(K key, V currentValue, V newValue);
91
92 /**
93 * Conditionally removed an entry for a specified key, iff:
94 * <ul>
95 * <li>An entry already exists for the key</li>
96 * <li>The current value matches the supplied <tt>value</tt> using {@link Object#equals(Object)}</li>
97 * </ul>
98 *
99 * @param key the key of the entry to remove conditionally
100 * @param value the current value to match
101 * @return whether an entry was removed
102 */
103 boolean removeIf(K key, V value);
104
105 /**
106 * Removes all the entries for the supplied keys. The same as calling {@link #remove(Iterable)} passing
107 * {@code Arrays.asList(keys)} as the argument.
108 *
109 * @param keys specifies the entries to be removed.
110 */
111 @SuppressWarnings("unchecked")
112 default void remove(K... keys)
113 {
114 remove(Arrays.asList(keys));
115 }
116
117 /**
118 * Removes all the entries for the supplied keys.
119 *
120 * @param keys specifies the entries to be removed.
121 */
122 void remove(Iterable<K> keys);
123
124 /**
125 * Removes all the entries in the cache.
126 */
127 void removeAll();
128
129 /**
130 * Returns the values that are associated with the specified keys. It is equivalent to calling
131 * {@link #getBulk(Iterable)} passing {@code Arrays.asList(keys)} as the parameter.
132 *
133 * @param keys the keys to check.
134 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
135 * {@link Optional} which may contain the value associated with the key.
136 */
137 @SuppressWarnings("unchecked")
138 @Nonnull
139 default Map<K, Optional<V>> getBulk(K... keys)
140 {
141 return getBulk(Arrays.asList(keys));
142 }
143
144 /**
145 * Returns the values that are associated with the specified keys.
146 *
147 * @param keys the keys to check.
148 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
149 * {@link Optional} which may contain the value associated with the key.
150 */
151 @Nonnull
152 Map<K, Optional<V>> getBulk(Iterable<K> keys);
153
154 /**
155 * Returns the values that are associated with the specified keys. It is equivalent to calling
156 * {@link #getBulk(Function, Iterable)} passing {@code factory} and {@code Arrays.asList(keys)} as the parameters.
157 * <p>Notes:</p>
158 * <ul>
159 * <li>
160 * If no entry for the specified key exists, then the specified <tt>factory</tt> is called, sequentially
161 * using the current thread, to create an entry in the cache, before it is returned.
162 * </li>
163 * </ul>
164 *
165 * @param factory used to generate the values for the keys that do not have entries. The factory must return a
166 * map containing a non-null entry for each supplied key.
167 * @param keys the keys to retrieve
168 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
169 * the value associated with the key.
170 */
171 @SuppressWarnings("unchecked")
172 @Nonnull
173 default Map<K, V> getBulk(Function<Collection<K>, Map<K, V>> factory, K... keys)
174 {
175 return getBulk(factory, Arrays.asList(keys));
176 }
177
178 /**
179 * Returns the values that are associated with the specified keys.
180 * <p>Notes:</p>
181 * <ul>
182 * <li>
183 * If no entry for the specified key exists, then the specified <tt>factory</tt> is called, sequentially
184 * using the current thread, to create an entry in the cache, before it is returned.
185 * </li>
186 * </ul>
187 *
188 * @param factory used to generate the values for the keys that do not have entries. The factory must return a
189 * map containing a non-null entry for each supplied key.
190 * @param keys the keys to retrieve
191 * @return A {@link Map} that is keyed on the {@code keys} specified. Each entry in the {@link Map} will have
192 * the value associated with the key.
193 */
194 @Nonnull
195 Map<K, V> getBulk(Function<Collection<K>, Map<K, V>> factory, Iterable<K> keys);
196 }