1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| package org.jboss.cache.pojo.collection; |
8 |
| |
9 |
| import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION; |
10 |
| |
11 |
| import java.io.Serializable; |
12 |
| import java.util.AbstractCollection; |
13 |
| import java.util.AbstractSet; |
14 |
| import java.util.ArrayList; |
15 |
| import java.util.Collection; |
16 |
| import java.util.Collections; |
17 |
| import java.util.Iterator; |
18 |
| import java.util.Map; |
19 |
| import java.util.Set; |
20 |
| |
21 |
| import org.jboss.aop.Advised; |
22 |
| import org.jboss.cache.Cache; |
23 |
| import org.jboss.cache.CacheSPI; |
24 |
| import org.jboss.cache.Fqn; |
25 |
| import org.jboss.cache.Node; |
26 |
| import org.jboss.cache.pojo.PojoCacheException; |
27 |
| import org.jboss.cache.pojo.annotation.Reentrant; |
28 |
| import org.jboss.cache.pojo.impl.PojoCacheImpl; |
29 |
| import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor; |
30 |
| import org.jboss.cache.pojo.util.CacheApiUtil; |
31 |
| import org.jboss.cache.pojo.util.Null; |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| |
38 |
| |
39 |
| @Reentrant |
40 |
| public class CachedMapImpl implements Map |
41 |
| { |
42 |
| private PojoCacheImpl pojoCache; |
43 |
| private Cache<Object, Object> cache; |
44 |
| private AbstractCollectionInterceptor interceptor; |
45 |
| |
46 |
110
| public CachedMapImpl(PojoCacheImpl pCache, AbstractCollectionInterceptor interceptor)
|
47 |
| { |
48 |
110
| this.pojoCache = pCache;
|
49 |
110
| this.cache = pojoCache.getCache();
|
50 |
110
| this.interceptor = interceptor;
|
51 |
| } |
52 |
| |
53 |
517
| private static Fqn constructFqn(Fqn baseFqn, Object relative)
|
54 |
| { |
55 |
517
| if (!(relative instanceof Serializable) && !(relative instanceof Advised))
|
56 |
| { |
57 |
2
| throw new PojoCacheException("Non-serializable for " + relative.getClass().getName());
|
58 |
| } |
59 |
| |
60 |
515
| return new Fqn(baseFqn, relative);
|
61 |
| } |
62 |
| |
63 |
809
| private Fqn getFqn()
|
64 |
| { |
65 |
809
| return interceptor.getFqn();
|
66 |
| } |
67 |
| |
68 |
248
| private Object attach(Object key, Object value)
|
69 |
| { |
70 |
248
| Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
|
71 |
246
| Object o = pojoCache.attach(fqn, Null.toNullObject(value));
|
72 |
246
| pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "PUT");
|
73 |
| |
74 |
246
| return o;
|
75 |
| } |
76 |
| |
77 |
57
| private Object detach(Object key)
|
78 |
| { |
79 |
57
| Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
|
80 |
57
| pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
|
81 |
| |
82 |
57
| return pojoCache.detach(fqn);
|
83 |
| } |
84 |
| |
85 |
| |
86 |
| |
87 |
292
| private Set<Node> getNodeChildren()
|
88 |
| { |
89 |
292
| return CacheApiUtil.getNodeChildren(cache, getFqn());
|
90 |
| } |
91 |
| |
92 |
159
| public Object get(Object key)
|
93 |
| { |
94 |
159
| return Null.toNullValue(pojoCache.getObject(constructFqn(getFqn(), Null.toNullKeyObject(key))));
|
95 |
| } |
96 |
| |
97 |
248
| public Object put(Object key, Object value)
|
98 |
| { |
99 |
248
| return attach(key, value);
|
100 |
| } |
101 |
| |
102 |
2
| public void putAll(Map map)
|
103 |
| { |
104 |
2
| for (Iterator i = map.entrySet().iterator(); i.hasNext();)
|
105 |
| { |
106 |
4
| Map.Entry entry = (Map.Entry) i.next();
|
107 |
4
| put(entry.getKey(), entry.getValue());
|
108 |
| } |
109 |
| } |
110 |
| |
111 |
57
| public Object remove(Object key)
|
112 |
| { |
113 |
57
| return detach(key);
|
114 |
| } |
115 |
| |
116 |
4
| public void clear()
|
117 |
| { |
118 |
| |
119 |
4
| ArrayList list = new ArrayList(keySet());
|
120 |
4
| for (int i = 0; i < list.size(); i++)
|
121 |
| { |
122 |
11
| remove(list.get(i));
|
123 |
| } |
124 |
| } |
125 |
| |
126 |
128
| public int size()
|
127 |
| { |
128 |
128
| Set<Node> children = getNodeChildren();
|
129 |
128
| return children == null ? 0 : children.size();
|
130 |
| } |
131 |
| |
132 |
2
| public boolean isEmpty()
|
133 |
| { |
134 |
2
| return size() == 0;
|
135 |
| } |
136 |
| |
137 |
23
| public boolean containsKey(Object object)
|
138 |
| { |
139 |
23
| Set<Node> children = getNodeChildren();
|
140 |
0
| if (children == null) return false;
|
141 |
23
| for (Object n : children)
|
142 |
| { |
143 |
15
| if (((Node) n).getFqn().getLastElement().equals(Null.toNullKeyObject(object))) return true;
|
144 |
| } |
145 |
| |
146 |
8
| return false;
|
147 |
| } |
148 |
| |
149 |
9
| public boolean containsValue(Object object)
|
150 |
| { |
151 |
9
| return values().contains(Null.toNullObject(object));
|
152 |
| } |
153 |
| |
154 |
39
| public Set entrySet()
|
155 |
| { |
156 |
39
| final CachedMapImpl map = this;
|
157 |
| |
158 |
39
| return new AbstractSet()
|
159 |
| { |
160 |
| |
161 |
2
| public int size()
|
162 |
| { |
163 |
2
| Set<Node> children = getNodeChildren();
|
164 |
2
| return children == null ? 0 : children.size();
|
165 |
| } |
166 |
| |
167 |
37
| public Iterator iterator()
|
168 |
| { |
169 |
37
| Set<Node> children = getNodeChildren();
|
170 |
37
| final Iterator i =
|
171 |
37
| children == null
|
172 |
| ? Collections.EMPTY_LIST.iterator() |
173 |
| : children.iterator(); |
174 |
37
| return new Iterator()
|
175 |
| { |
176 |
| Object lastKey; |
177 |
| |
178 |
75
| public boolean hasNext()
|
179 |
| { |
180 |
75
| return i.hasNext();
|
181 |
| } |
182 |
| |
183 |
53
| public Object next()
|
184 |
| { |
185 |
53
| return new Entry(lastKey = ((Node) i.next()).getFqn().getLastElement());
|
186 |
| } |
187 |
| |
188 |
0
| public void remove()
|
189 |
| { |
190 |
0
| map.remove(lastKey);
|
191 |
| } |
192 |
| }; |
193 |
| } |
194 |
| }; |
195 |
| } |
196 |
| |
197 |
16
| public Collection values()
|
198 |
| { |
199 |
16
| final CachedMapImpl map = this;
|
200 |
| |
201 |
16
| return new AbstractCollection()
|
202 |
| { |
203 |
| |
204 |
10
| public int size()
|
205 |
| { |
206 |
10
| Set<Node> children = getNodeChildren();
|
207 |
10
| return children == null ? 0 : children.size();
|
208 |
| } |
209 |
| |
210 |
2
| public void clear()
|
211 |
| { |
212 |
2
| map.clear();
|
213 |
| } |
214 |
| |
215 |
29
| public Iterator iterator()
|
216 |
| { |
217 |
29
| Set<Node> children = getNodeChildren();
|
218 |
29
| final Iterator i =
|
219 |
29
| children == null
|
220 |
| ? Collections.EMPTY_LIST.iterator() |
221 |
| : children.iterator(); |
222 |
| |
223 |
29
| return new Iterator()
|
224 |
| { |
225 |
| Object lastKey; |
226 |
| |
227 |
78
| public boolean hasNext()
|
228 |
| { |
229 |
78
| return i.hasNext();
|
230 |
| } |
231 |
| |
232 |
70
| public Object next()
|
233 |
| { |
234 |
70
| Fqn f = ((Node) i.next()).getFqn();
|
235 |
70
| lastKey = f.getLastElement();
|
236 |
70
| return Null.toNullValue(pojoCache.getObject(f));
|
237 |
| } |
238 |
| |
239 |
6
| public void remove()
|
240 |
| { |
241 |
6
| Object key = lastKey;
|
242 |
6
| if (key != null)
|
243 |
6
| key = Null.toNullKeyValue(key);
|
244 |
6
| map.remove(key);
|
245 |
| } |
246 |
| }; |
247 |
| } |
248 |
| }; |
249 |
| } |
250 |
| |
251 |
55
| public Set keySet()
|
252 |
| { |
253 |
55
| final CachedMapImpl map = this;
|
254 |
| |
255 |
55
| return new AbstractSet()
|
256 |
| { |
257 |
| |
258 |
10
| public int size()
|
259 |
| { |
260 |
10
| Set<Node> children = getNodeChildren();
|
261 |
10
| return children == null ? 0 : children.size();
|
262 |
| } |
263 |
| |
264 |
53
| public Iterator iterator()
|
265 |
| { |
266 |
53
| Set<Node> children = getNodeChildren();
|
267 |
53
| final Iterator i =
|
268 |
53
| children == null
|
269 |
| ? Collections.EMPTY_LIST.iterator() |
270 |
| : children.iterator(); |
271 |
| |
272 |
53
| return new Iterator()
|
273 |
| { |
274 |
| Object lastKey; |
275 |
| |
276 |
195
| public boolean hasNext()
|
277 |
| { |
278 |
195
| return i.hasNext();
|
279 |
| } |
280 |
| |
281 |
102
| public Object next()
|
282 |
| { |
283 |
102
| lastKey = ((Node) i.next()).getFqn().getLastElement();
|
284 |
102
| return Null.toNullKeyValue(lastKey);
|
285 |
| |
286 |
| } |
287 |
| |
288 |
2
| public void remove()
|
289 |
| { |
290 |
2
| Object key = lastKey;
|
291 |
2
| if (key != null)
|
292 |
2
| key = Null.toNullKeyValue(key);
|
293 |
2
| map.remove(key);
|
294 |
| } |
295 |
| }; |
296 |
| |
297 |
| } |
298 |
| }; |
299 |
| } |
300 |
| |
301 |
0
| public int hashCode()
|
302 |
| { |
303 |
0
| int result = 0;
|
304 |
0
| for (Iterator i = entrySet().iterator(); i.hasNext();)
|
305 |
| { |
306 |
0
| result += i.next().hashCode();
|
307 |
| } |
308 |
0
| return result;
|
309 |
| } |
310 |
| |
311 |
30
| public boolean equals(Object object)
|
312 |
| { |
313 |
30
| if (object == this)
|
314 |
0
| return true;
|
315 |
30
| if (object == null || !(object instanceof Map))
|
316 |
0
| return false;
|
317 |
30
| Map map = (Map) object;
|
318 |
30
| if (size() != map.size())
|
319 |
0
| return false;
|
320 |
30
| for (Iterator i = entrySet().iterator(); i.hasNext();)
|
321 |
| { |
322 |
40
| Entry entry = (Entry) i.next();
|
323 |
40
| Object value = entry.getValue();
|
324 |
40
| Object key = entry.getKey();
|
325 |
40
| if (value == null)
|
326 |
| { |
327 |
3
| if (!(map.get(key) == null && map.containsKey(key)))
|
328 |
| { |
329 |
0
| return false;
|
330 |
| } |
331 |
| } else |
332 |
| { |
333 |
37
| if (!value.equals(map.get(key)))
|
334 |
5
| return false;
|
335 |
| } |
336 |
| } |
337 |
25
| return true;
|
338 |
| } |
339 |
| |
340 |
29
| public String toString()
|
341 |
| { |
342 |
29
| StringBuffer buf = new StringBuffer();
|
343 |
29
| Set set = keySet();
|
344 |
29
| for (Iterator it = set.iterator(); it.hasNext();)
|
345 |
| { |
346 |
56
| Object key = it.next();
|
347 |
56
| buf.append("[").append(key).append(", ").append(get(key)).append("]");
|
348 |
27
| if (it.hasNext()) buf.append(", ");
|
349 |
| } |
350 |
| |
351 |
29
| return buf.toString();
|
352 |
| } |
353 |
| |
354 |
| class Entry implements Map.Entry |
355 |
| { |
356 |
| |
357 |
| Object key; |
358 |
| |
359 |
53
| public Entry(Object key)
|
360 |
| { |
361 |
53
| this.key = key;
|
362 |
| } |
363 |
| |
364 |
48
| public Object getKey()
|
365 |
| { |
366 |
48
| return Null.toNullValue(key);
|
367 |
| } |
368 |
| |
369 |
53
| public Object getValue()
|
370 |
| { |
371 |
53
| return Null.toNullValue(pojoCache.getObject(constructFqn(getFqn(), key)));
|
372 |
| } |
373 |
| |
374 |
0
| public Object setValue(Object value)
|
375 |
| { |
376 |
0
| return attach(key, value);
|
377 |
| } |
378 |
| |
379 |
0
| public int hashCode()
|
380 |
| { |
381 |
0
| Object value = getValue();
|
382 |
0
| return ((key == null) ? 0 : key.hashCode())
|
383 |
0
| ^ ((value == null) ? 0 : value.hashCode());
|
384 |
| } |
385 |
| |
386 |
0
| public boolean equals(Object obj)
|
387 |
| { |
388 |
0
| if (!(obj instanceof Entry))
|
389 |
0
| return false;
|
390 |
0
| Entry entry = (Entry) obj;
|
391 |
0
| Object value = getValue();
|
392 |
0
| return (
|
393 |
0
| key == null
|
394 |
| ? entry.getKey() == null |
395 |
| : key.equals(entry.getKey())) |
396 |
0
| && (value == null
|
397 |
| ? entry.getValue() == null |
398 |
| : value.equals(entry.getValue())); |
399 |
| } |
400 |
| } |
401 |
| |
402 |
| |
403 |
| } |