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.util.AbstractSet; |
12 |
| import java.util.Collection; |
13 |
| import java.util.Collections; |
14 |
| import java.util.HashSet; |
15 |
| import java.util.Iterator; |
16 |
| import java.util.Set; |
17 |
| |
18 |
| import org.jboss.cache.Cache; |
19 |
| import org.jboss.cache.CacheException; |
20 |
| import org.jboss.cache.CacheSPI; |
21 |
| import org.jboss.cache.Fqn; |
22 |
| import org.jboss.cache.Node; |
23 |
| import org.jboss.cache.NodeSPI; |
24 |
| import org.jboss.cache.pojo.annotation.Reentrant; |
25 |
| import org.jboss.cache.pojo.impl.PojoCacheImpl; |
26 |
| import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor; |
27 |
| import org.jboss.cache.pojo.util.AopUtil; |
28 |
| import org.jboss.cache.pojo.util.CacheApiUtil; |
29 |
| import org.jboss.cache.pojo.util.Null; |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| |
38 |
| |
39 |
| |
40 |
| |
41 |
| |
42 |
| @Reentrant |
43 |
| public class CachedSetImpl extends AbstractSet |
44 |
| { |
45 |
| private PojoCacheImpl pojoCache; |
46 |
| private Cache<Object, Object> cache; |
47 |
| private AbstractCollectionInterceptor interceptor; |
48 |
| |
49 |
66
| public CachedSetImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
|
50 |
| { |
51 |
66
| this.pojoCache = cache;
|
52 |
66
| this.cache = pojoCache.getCache();
|
53 |
66
| this.interceptor = interceptor;
|
54 |
| } |
55 |
| |
56 |
295
| private Set<Node> getNodeChildren()
|
57 |
| { |
58 |
295
| return CacheApiUtil.getNodeChildren(cache, getFqn());
|
59 |
| } |
60 |
| |
61 |
805
| private Fqn getFqn()
|
62 |
| { |
63 |
| |
64 |
805
| return interceptor.getFqn();
|
65 |
| } |
66 |
| |
67 |
| |
68 |
| |
69 |
158
| public boolean add(Object o)
|
70 |
| { |
71 |
158
| o = Null.toNullObject(o);
|
72 |
158
| int hashCode = o.hashCode();
|
73 |
158
| int size = size();
|
74 |
174
| for (int i = 0; i < size + 1; i++)
|
75 |
| { |
76 |
174
| Object key = toLong(hashCode, i);
|
77 |
174
| Object o2 = getNoUnmask(key);
|
78 |
174
| if (o2 == null)
|
79 |
| { |
80 |
152
| attach(key, o, true);
|
81 |
152
| return true;
|
82 |
| } |
83 |
22
| if (o.equals(o2))
|
84 |
| { |
85 |
6
| return false;
|
86 |
| } |
87 |
| } |
88 |
| |
89 |
0
| throw new CacheException();
|
90 |
| } |
91 |
| |
92 |
3
| public void clear()
|
93 |
| { |
94 |
3
| Set<Node> children = getNodeChildren();
|
95 |
3
| for (Node n : children)
|
96 |
| { |
97 |
9
| pojoCache.detach(n.getFqn());
|
98 |
| } |
99 |
| } |
100 |
| |
101 |
25
| public boolean contains(Object o)
|
102 |
| { |
103 |
25
| o = Null.toNullObject(o);
|
104 |
25
| int hashCode = o.hashCode();
|
105 |
25
| int size = size();
|
106 |
25
| for (int i = 0; i < size; i++)
|
107 |
| { |
108 |
25
| Object key = toLong(hashCode, i);
|
109 |
25
| Object o2 = getNoUnmask(key);
|
110 |
25
| if (o2 == null)
|
111 |
| { |
112 |
6
| return false;
|
113 |
| } |
114 |
19
| if (o.equals(o2))
|
115 |
| { |
116 |
19
| return true;
|
117 |
| } |
118 |
| } |
119 |
0
| return false;
|
120 |
| } |
121 |
| |
122 |
41
| public Iterator iterator()
|
123 |
| { |
124 |
41
| Node node = cache.getRoot().getChild(getFqn());
|
125 |
41
| if (node == null)
|
126 |
| { |
127 |
0
| return Collections.EMPTY_SET.iterator();
|
128 |
| } |
129 |
41
| return new IteratorImpl(node);
|
130 |
| } |
131 |
| |
132 |
42
| public boolean remove(Object o)
|
133 |
| { |
134 |
42
| o = Null.toNullObject(o);
|
135 |
42
| int hashCode = o.hashCode();
|
136 |
42
| int size = size();
|
137 |
42
| boolean removed = false;
|
138 |
42
| Object oldkey = null;
|
139 |
42
| for (int i = 0; i < size; i++)
|
140 |
| { |
141 |
71
| Object key = toLong(hashCode, i);
|
142 |
71
| Object o2 = getNoUnmask(key);
|
143 |
71
| if (o2 == null)
|
144 |
| { |
145 |
23
| break;
|
146 |
| } |
147 |
48
| if (removed)
|
148 |
| { |
149 |
| |
150 |
3
| detach(key);
|
151 |
3
| attach(oldkey, o2);
|
152 |
| } |
153 |
48
| if (o.equals(o2))
|
154 |
| { |
155 |
41
| detach(key, true);
|
156 |
41
| removed = true;
|
157 |
| } |
158 |
48
| oldkey = key;
|
159 |
| } |
160 |
42
| return removed;
|
161 |
| } |
162 |
| |
163 |
292
| public int size()
|
164 |
| { |
165 |
292
| Set<Node> children = getNodeChildren();
|
166 |
292
| return (children == null) ? 0 : children.size();
|
167 |
| } |
168 |
| |
169 |
3
| public String toString()
|
170 |
| { |
171 |
3
| StringBuffer buf = new StringBuffer();
|
172 |
3
| for (Iterator it = iterator(); it.hasNext();)
|
173 |
| { |
174 |
7
| Object key = it.next();
|
175 |
7
| buf.append("[").append(key).append("]");
|
176 |
4
| if (it.hasNext()) buf.append(", ");
|
177 |
| } |
178 |
| |
179 |
3
| return buf.toString();
|
180 |
| } |
181 |
| |
182 |
| |
183 |
| |
184 |
| |
185 |
| |
186 |
| |
187 |
270
| private String toLong(long hashCode, long count)
|
188 |
| { |
189 |
270
| long key = (hashCode & 0xFFFFL) | (count << 32);
|
190 |
270
| return Long.toHexString(key);
|
191 |
| } |
192 |
| |
193 |
| |
194 |
3
| private Object attach(Object key, Object pojo)
|
195 |
| { |
196 |
3
| return attach(key, pojo, false);
|
197 |
| } |
198 |
| |
199 |
155
| private Object attach(Object key, Object pojo, boolean add)
|
200 |
| { |
201 |
155
| Fqn fqn = AopUtil.constructFqn(getFqn(), key);
|
202 |
155
| Object o = pojoCache.attach(fqn, pojo);
|
203 |
155
| if (add)
|
204 |
152
| pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "ADD");
|
205 |
| |
206 |
155
| return o;
|
207 |
| } |
208 |
| |
209 |
3
| private Object detach(Object key)
|
210 |
| { |
211 |
3
| return detach(key, false);
|
212 |
| } |
213 |
| |
214 |
44
| private Object detach(Object key, boolean remove)
|
215 |
| { |
216 |
44
| Fqn fqn = AopUtil.constructFqn(getFqn(), key);
|
217 |
44
| if (remove)
|
218 |
41
| pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
|
219 |
| |
220 |
44
| return pojoCache.detach(fqn);
|
221 |
| } |
222 |
| |
223 |
270
| private Object getNoUnmask(Object key)
|
224 |
| { |
225 |
270
| return pojoCache.getObject(AopUtil.constructFqn(getFqn(), key));
|
226 |
| } |
227 |
| |
228 |
1
| public int hashCode()
|
229 |
| { |
230 |
1
| int result = super.hashCode();
|
231 |
1
| result = 29 * result + cache.hashCode();
|
232 |
1
| result = 29 * result + interceptor.hashCode();
|
233 |
1
| return result;
|
234 |
| } |
235 |
| |
236 |
6
| public boolean equals(Object o)
|
237 |
| { |
238 |
6
| if (o == this)
|
239 |
| { |
240 |
0
| return true;
|
241 |
| } |
242 |
| |
243 |
6
| try
|
244 |
| { |
245 |
6
| return super.equals(o);
|
246 |
| } |
247 |
| catch (ClassCastException e) |
248 |
| { |
249 |
0
| return false;
|
250 |
| } |
251 |
| catch (NullPointerException unused) |
252 |
| { |
253 |
0
| return false;
|
254 |
| } |
255 |
| } |
256 |
| |
257 |
| private class IteratorImpl implements Iterator |
258 |
| { |
259 |
| private Iterator<NodeSPI> iterator; |
260 |
| |
261 |
| private Node node; |
262 |
| private Object o; |
263 |
| |
264 |
41
| private IteratorImpl(Node node)
|
265 |
| { |
266 |
41
| Collection<NodeSPI> children = new HashSet<NodeSPI>(((NodeSPI) node).getChildrenDirect());
|
267 |
41
| iterator = children.iterator();
|
268 |
| } |
269 |
| |
270 |
111
| public boolean hasNext()
|
271 |
| { |
272 |
111
| return iterator.hasNext();
|
273 |
| } |
274 |
| |
275 |
92
| public Object next()
|
276 |
| { |
277 |
92
| node = iterator.next();
|
278 |
91
| o = Null.toNullValue(pojoCache.getObject(node.getFqn()));
|
279 |
91
| return o;
|
280 |
| } |
281 |
| |
282 |
29
| public void remove() throws IllegalStateException
|
283 |
| { |
284 |
29
| if (node == null)
|
285 |
| { |
286 |
1
| throw new IllegalStateException();
|
287 |
| } |
288 |
28
| CachedSetImpl.this.remove(o);
|
289 |
| } |
290 |
| |
291 |
| } |
292 |
| } |