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