1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.jcs3.jcache;
20
21 import javax.cache.Cache;
22 import javax.cache.CacheManager;
23 import javax.cache.configuration.CacheEntryListenerConfiguration;
24 import javax.cache.configuration.CompleteConfiguration;
25 import javax.cache.configuration.Configuration;
26 import javax.cache.integration.CompletionListener;
27 import javax.cache.processor.EntryProcessor;
28 import javax.cache.processor.EntryProcessorException;
29 import javax.cache.processor.EntryProcessorResult;
30
31 import static org.apache.commons.jcs3.jcache.Asserts.assertNotNull;
32
33 import java.util.Collection;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.LinkedList;
38 import java.util.Map;
39 import java.util.Set;
40
41
42 public class TempStateCacheView<K, V> implements Cache<K, V>
43 {
44 private final JCSCache<K, V> cache;
45 private final Map<K, V> put = new HashMap<>();
46 private final Collection<K> remove = new LinkedList<>();
47 private boolean removeAll;
48 private boolean clear;
49
50 public TempStateCacheView(final JCSCache<K, V> entries)
51 {
52 this.cache = entries;
53 }
54
55 @Override
56 public V get(final K key)
57 {
58 if (ignoreKey(key))
59 {
60 return null;
61 }
62
63 final V v = put.get(key);
64 if (v != null)
65 {
66 return v;
67 }
68
69
70
71 if (cache.getConfiguration(CompleteConfiguration.class).isStatisticsEnabled())
72 {
73 final Statistics statistics = cache.getStatistics();
74 if (cache.containsKey(key))
75 {
76 statistics.increaseHits(-1);
77 }
78 else
79 {
80 statistics.increaseMisses(-1);
81 }
82 }
83 return cache.get(key);
84 }
85
86 private boolean ignoreKey(final K key)
87 {
88 return removeAll || clear || remove.contains(key);
89 }
90
91 @Override
92 public Map<K, V> getAll(final Set<? extends K> keys)
93 {
94 final Map<K, V> v = new HashMap<>(keys.size());
95 final Set<K> missing = new HashSet<>();
96 for (final K k : keys)
97 {
98 final V value = put.get(k);
99 if (value != null)
100 {
101 v.put(k, value);
102 }
103 else if (!ignoreKey(k))
104 {
105 missing.add(k);
106 }
107 }
108 if (!missing.isEmpty())
109 {
110 v.putAll(cache.getAll(missing));
111 }
112 return v;
113 }
114
115 @Override
116 public boolean containsKey(final K key)
117 {
118 return !ignoreKey(key) && (put.containsKey(key) || cache.containsKey(key));
119 }
120
121 @Override
122 public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
123 {
124 cache.loadAll(keys, replaceExistingValues, completionListener);
125 }
126
127 @Override
128 public void put(final K key, final V value)
129 {
130 assertNotNull(key, "key");
131 assertNotNull(value, "value");
132 put.put(key, value);
133 remove.remove(key);
134 }
135
136 @Override
137 public V getAndPut(final K key, final V value)
138 {
139 final V v = get(key);
140 put(key, value);
141 return v;
142 }
143
144 @Override
145 public void putAll(final Map<? extends K, ? extends V> map)
146 {
147 put.putAll(map);
148 for (final K k : map.keySet())
149 {
150 remove.remove(k);
151 }
152 }
153
154 @Override
155 public boolean putIfAbsent(final K key, final V value)
156 {
157 if (!put.containsKey(key))
158 {
159 put.put(key, value);
160 remove.remove(key);
161 return true;
162 }
163 return false;
164 }
165
166 @Override
167 public boolean remove(final K key)
168 {
169 final boolean noop = put.containsKey(key);
170 put.remove(key);
171 if (!ignoreKey(key))
172 {
173 if (!noop)
174 {
175 remove.add(key);
176 }
177 return true;
178 }
179 return false;
180 }
181
182 @Override
183 public boolean remove(final K key, final V oldValue)
184 {
185 put.remove(key);
186 if (!ignoreKey(key) && oldValue.equals(cache.get(key)))
187 {
188 remove.add(key);
189 return true;
190 }
191 return false;
192 }
193
194 @Override
195 public V getAndRemove(final K key)
196 {
197 final V v = get(key);
198 remove.add(key);
199 put.remove(key);
200 return v;
201 }
202
203 @Override
204 public boolean replace(final K key, final V oldValue, final V newValue)
205 {
206 if (oldValue.equals(get(key)))
207 {
208 put(key, newValue);
209 return true;
210 }
211 return false;
212 }
213
214 @Override
215 public boolean replace(final K key, final V value)
216 {
217 if (containsKey(key))
218 {
219 remove(key);
220 return true;
221 }
222 return false;
223 }
224
225 @Override
226 public V getAndReplace(final K key, final V value)
227 {
228 if (containsKey(key))
229 {
230 final V oldValue = get(key);
231 put(key, value);
232 return oldValue;
233 }
234 return null;
235 }
236
237 @Override
238 public void removeAll(final Set<? extends K> keys)
239 {
240 remove.addAll(keys);
241 for (final K k : keys)
242 {
243 put.remove(k);
244 }
245 }
246
247 @Override
248 public void removeAll()
249 {
250 removeAll = true;
251 put.clear();
252 remove.clear();
253 }
254
255 @Override
256 public void clear()
257 {
258 clear = true;
259 put.clear();
260 remove.clear();
261 }
262
263 @Override
264 public <C extends Configuration<K, V>> C getConfiguration(final Class<C> clazz)
265 {
266 return cache.getConfiguration(clazz);
267 }
268
269 @Override
270 public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException
271 {
272 return cache.invoke(key, entryProcessor, arguments);
273 }
274
275 @Override
276 public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys, final EntryProcessor<K, V, T> entryProcessor,
277 final Object... arguments)
278 {
279 return cache.invokeAll(keys, entryProcessor, arguments);
280 }
281
282 @Override
283 public String getName()
284 {
285 return cache.getName();
286 }
287
288 @Override
289 public CacheManager getCacheManager()
290 {
291 return cache.getCacheManager();
292 }
293
294 @Override
295 public void close()
296 {
297 cache.close();
298 }
299
300 @Override
301 public boolean isClosed()
302 {
303 return cache.isClosed();
304 }
305
306 @Override
307 public <T> T unwrap(final Class<T> clazz)
308 {
309 return cache.unwrap(clazz);
310 }
311
312 @Override
313 public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
314 {
315 cache.registerCacheEntryListener(cacheEntryListenerConfiguration);
316 }
317
318 @Override
319 public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
320 {
321 cache.deregisterCacheEntryListener(cacheEntryListenerConfiguration);
322 }
323
324 @Override
325 public Iterator<Entry<K, V>> iterator()
326 {
327 return cache.iterator();
328 }
329
330 public void merge()
331 {
332 if (removeAll)
333 {
334 cache.removeAll();
335 }
336 if (clear)
337 {
338 cache.clear();
339 }
340
341 for (final Map.Entry<K, V> entry : put.entrySet())
342 {
343 cache.put(entry.getKey(), entry.getValue());
344 }
345 put.clear();
346 for (final K entry : remove)
347 {
348 cache.remove(entry);
349 }
350 remove.clear();
351 }
352 }