EMMA Coverage Report (generated Thu Jan 20 11:39:44 EST 2011)
[all classes][com.hammurapi.store.local]

COVERAGE SUMMARY FOR SOURCE FILE [LocalHandle.java]

nameclass, %method, %block, %line, %
LocalHandle.java100% (3/3)81%  (17/21)64%  (398/624)65%  (80.7/125)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LocalHandle100% (1/1)80%  (12/15)60%  (333/554)63%  (75.9/120)
equals (Object): boolean 0%   (0/1)0%   (0/38)0%   (0/10)
hashCode (): int 0%   (0/1)0%   (0/9)0%   (0/3)
toString (): String 0%   (0/1)0%   (0/21)0%   (0/2)
getCache (): Map 100% (1/1)21%  (11/53)25%  (3/12)
get (): Object 100% (1/1)50%  (11/22)60%  (3/5)
update (Object): void 100% (1/1)58%  (59/101)70%  (16/23)
LocalHandle (LocalStoreBase, Object, Object, Map, Predicate [], LocalHandle$H... 100% (1/1)66%  (56/85)71%  (17/24)
remove (): void 100% (1/1)73%  (27/37)89%  (8/9)
isValid (): boolean 100% (1/1)86%  (57/66)92%  (11/12)
update (): void 100% (1/1)88%  (37/42)89%  (8/9)
extract (Extractor): Object 100% (1/1)89%  (16/18)75%  (3/4)
$SWITCH_TABLE$com$hammurapi$store$local$LocalHandle$HandleStrength (): int [] 100% (1/1)91%  (31/34)91%  (0.9/1)
deleteObserver (Object): void 100% (1/1)100% (11/11)100% (4/4)
getPrimaryKey (): Object 100% (1/1)100% (3/3)100% (1/1)
toObservable (Object): Observable 100% (1/1)100% (14/14)100% (1/1)
     
class LocalHandle$HandleStrength100% (1/1)75%  (3/4)92%  (55/60)92%  (2.8/3)
valueOf (String): LocalHandle$HandleStrength 0%   (0/1)0%   (0/5)0%   (0/1)
<static initializer> 100% (1/1)100% (34/34)100% (2/2)
LocalHandle$HandleStrength (String, int): void 100% (1/1)100% (5/5)100% (1/1)
values (): LocalHandle$HandleStrength [] 100% (1/1)100% (16/16)100% (1/1)
     
class LocalHandle$1100% (1/1)100% (2/2)100% (10/10)100% (4/4)
LocalHandle$1 (LocalHandle): void 100% (1/1)100% (6/6)100% (2/2)
update (Object, Object []): void 100% (1/1)100% (4/4)100% (2/2)

1package com.hammurapi.store.local;
2 
3import java.lang.ref.Reference;
4import java.lang.ref.SoftReference;
5import java.lang.ref.WeakReference;
6import java.util.Map;
7import java.util.concurrent.atomic.AtomicBoolean;
8 
9import com.hammurapi.common.Observable;
10import com.hammurapi.common.Observer;
11import com.hammurapi.common.Util;
12import com.hammurapi.extract.Extractor;
13import com.hammurapi.extract.Predicate;
14import com.hammurapi.store.Store;
15import com.hammurapi.store.Store.Handle;
16import com.hammurapi.store.StoreException;
17 
18public class LocalHandle<T,PK, S extends Store<T,PK,S>> implements Handle<T, PK, S> {
19        
20        private final Observer<T> observer = new Observer<T>() {
21 
22                @Override
23                public void update(T obj, Object... args) {
24                        LocalHandle.this.update();
25                }
26                
27        };
28 
29        public enum HandleStrength {
30                STRONG, SOFT, WEAK
31        }
32        
33        @Override
34        public int hashCode() {
35                if (isValid()) {
36                        return get().hashCode();
37                }
38                return 0;
39        }
40 
41        @Override
42        public boolean equals(Object obj) {
43                if (this == obj)
44                        return true;
45                if (obj == null)
46                        return false;
47                if (getClass() != obj.getClass())
48                        return false;
49                
50                @SuppressWarnings("unchecked")
51                LocalHandle<T,PK,S> other = (LocalHandle<T,PK,S>) obj;
52                if (isValid() && other.isValid()) {
53                        return get().equals(other.get());
54                }
55                return !other.isValid();
56        }
57 
58        private Reference<T> ref;
59        private T obj;
60        private AtomicBoolean valid = new AtomicBoolean(true);
61        private PK primaryKey;
62        
63        private Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> cache;
64        private Reference<Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>>> cacheRef;
65        private HandleStrength handleStrength;
66        private LocalStoreBase<T,PK,S> store;
67        private boolean cacheExtracted;
68        private Predicate<T, S>[] validators;
69        
70        public LocalHandle(
71                        LocalStoreBase<T,PK,S> store,
72                        T obj, 
73                        PK primaryKey, 
74                        Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> cache,        
75                        Predicate<T, S>[] validators,                         
76                        HandleStrength handleStrength, 
77                        boolean cacheExtracted) {
78 
79                this.store = store;
80                this.handleStrength = handleStrength;
81                this.cacheExtracted = cacheExtracted;
82                this.validators = validators;
83                
84                com.hammurapi.common.Observable<T> observable = toObservable(obj);
85                if (observable!=null) {
86                        observable.addObserver(observer);
87                }
88                
89                switch (handleStrength) {
90                case STRONG:
91                        this.obj = obj; 
92                        this.cache = cache;
93                        break;
94                case SOFT:
95                        ref = new SoftReference<T>(obj);
96                        if (cache!=null) {
97                                cacheRef = new SoftReference<Map<S,Map<Extractor<T,? super PK,S>,? super PK>>>(cache);
98                        }
99                        break;
100                case WEAK:
101                        ref = new WeakReference<T>(obj);
102                        if (cache!=null) {
103                                cacheRef = new WeakReference<Map<S,Map<Extractor<T,? super PK,S>,? super PK>>>(cache);
104                        }
105                        break;
106                }
107                this.primaryKey = primaryKey;
108                valid.set(true);
109        }
110                
111        @Override
112        public void update(T obj) {                        
113                Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> theCache = getCache();
114                if (cacheExtracted) {
115                        if (theCache!=null) {
116                                theCache.clear();
117                        }
118                }
119                
120                if (store.getPrimaryKeyExtractor()!=null) {
121                        @SuppressWarnings("unchecked")
122                        PK newPrimaryKey = store.getPrimaryKeyExtractor().extract((S) store, theCache, Util.wrap(obj));
123                        if (!primaryKey.equals(newPrimaryKey)) {
124                                throw new StoreException("Primary key of the update object is different from the original primary key, use Store.put() instead of Handle.update()");
125                        }
126                }
127                
128                store.updateIndices(this, false);
129                
130                switch (handleStrength) {
131                case STRONG:
132                        deleteObserver(this.obj);
133                        this.obj = obj; 
134                        break;
135                case SOFT:
136                        deleteObserver(ref==null ? null : ref.get());
137                        ref = new SoftReference<T>(obj);                        
138                        break;
139                case WEAK:
140                        deleteObserver(ref==null ? null : ref.get());
141                        ref = new WeakReference<T>(obj);
142                        break;
143                }
144                
145                com.hammurapi.common.Observable observable = toObservable(obj);
146                if (observable!=null) {
147                        observable.addObserver(observer);
148                }
149                
150                valid.set(true);
151        }
152 
153        @Override
154        public void update() {                        
155                if (cacheExtracted) {
156                        getCache().clear();
157                }
158                
159                if (store.getPrimaryKeyExtractor()!=null) {
160                        @SuppressWarnings("unchecked")
161                        PK newPrimaryKey = store.getPrimaryKeyExtractor().extract((S) store, getCache(), Util.wrap(obj));
162                        if (!primaryKey.equals(newPrimaryKey)) {
163                                throw new StoreException("Primary key of the updated object is different from the original primary key, use Store.put() instead of Handle.update()");
164                        }
165                }
166                
167                store.updateIndices(this, false);
168                valid.set(true);
169        }
170        
171        @Override
172        public void remove() {
173                if (HandleStrength.STRONG.equals(handleStrength)) {
174                        deleteObserver(this.obj);
175                } else {
176                        deleteObserver(ref==null ? null : ref.get());
177                }
178                
179                valid.set(false);
180                obj = null;
181                ref = null;                
182                cache = null;
183                cacheRef = null;
184        }
185        
186        private void deleteObserver(T obj) {
187                com.hammurapi.common.Observable<T> observable = toObservable(obj);
188                if (observable!=null) {
189                        observable.deleteObserver(observer);
190                }                
191        }
192 
193        protected Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> getCache() {
194                if (valid.get()) {
195                        if (handleStrength==HandleStrength.STRONG) {
196                                return cache;
197                        }
198                        Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> ret = cacheRef==null ? null : cacheRef.get();
199                        if (ret==null && cacheExtracted) {
200                                ret = store.createCache();
201                                switch (handleStrength) {
202                                case SOFT:
203                                        cacheRef = new SoftReference<Map<S,Map<Extractor<T,? super PK,S>,? super PK>>>(ret);
204                                        break;
205                                case WEAK:
206                                        cacheRef = new WeakReference<Map<S,Map<Extractor<T,? super PK,S>,? super PK>>>(ret);
207                                        break;
208                                }
209                        }
210                        
211                        return ret; 
212                }
213                return null;
214        }
215        
216        @Override
217        public T get() {
218                if (isValid()) {
219                        if (HandleStrength.STRONG.equals(handleStrength)) {
220                                return obj;
221                        }
222                        return ref==null ? null : ref.get();
223                }
224                return null;
225        }
226 
227        @Override
228        public PK getPrimaryKey() {
229                return primaryKey;
230        }
231        
232        public boolean isValid() {                
233                if (!valid.get()) {
234                        return false;
235                }
236                
237                T theObj;
238                if (HandleStrength.STRONG.equals(handleStrength)) {
239                        theObj = obj;
240                } else {
241                        theObj = ref==null ? null : ref.get();
242                }
243                if (theObj==null) {
244                        return false;
245                }
246                if (validators!=null && validators.length>0) {
247//                        S deputy = store.createDeputy(); // Do we need deputy here???
248                        for (Predicate<T, S> v: validators) {
249                                if (!v.extract((S) store /* deputy */, null, Util.wrap(theObj))) {
250                                        return false;
251                                }
252                        }
253                }
254                return true;
255        }
256 
257        @Override
258        public <V> V extract(Extractor<T, V, S> extractor) {
259                if (isValid()) {
260                        // Rude cast because cache is intentionally of wrong value type (PK) instead of Object for convenience. 
261                        Map<S, Map<Extractor<T, ? super V, S>, ? super V>> theCache = (Map) getCache(); 
262                        return extractor.extract(store.createDeputy(), theCache, Util.wrap(get()));
263                } 
264                
265                return null;
266        }
267 
268        @Override
269        public String toString() {
270                return "HandleImpl [get()=" + get() + ", getPrimaryKey()="
271                                + getPrimaryKey() + ", isValid()=" + isValid() + "]";
272        }
273        
274        // TODO equals() and hashCode() for unique stores.                
275        
276        private Observable<T> toObservable(T obj) {
277                return store.config.getObservableConverter()==null ? null : store.config.getObservableConverter().convert(obj);
278        }
279                
280}

[all classes][com.hammurapi.store.local]
EMMA 2.0.5312 EclEmma Fix 2 (C) Vladimir Roubtsov