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

COVERAGE SUMMARY FOR SOURCE FILE [LocalStringPropertySet.java]

nameclass, %method, %block, %line, %
LocalStringPropertySet.java100% (2/2)88%  (15/17)69%  (415/600)68%  (68.4/101)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LocalStringPropertySet100% (1/1)87%  (13/15)62%  (236/380)62%  (45.5/73)
buildPath (String, Object []): String 0%   (0/1)0%   (0/27)0%   (0/5)
version (Object): Object 0%   (0/1)0%   (0/64)0%   (0/15)
LocalStringPropertySet (ExecutorService, Converter, Context, String, ClassLoa... 100% (1/1)55%  (44/80)62%  (8/13)
newInstance (String): AbstractPropertySet 100% (1/1)70%  (32/46)86%  (9.5/11)
getAdapter (Class, Context): Object 100% (1/1)91%  (21/23)75%  (3/4)
LocalStringPropertySet (ExecutorService, Converter, Context, String, ClassLoa... 100% (1/1)96%  (23/24)99%  (4/4)
<static initializer> 100% (1/1)100% (7/7)100% (3/3)
LocalStringPropertySet (ExecutorService, Converter, Context, ClassLoader, Pro... 100% (1/1)100% (9/9)100% (2/2)
access$5 (): int 100% (1/1)100% (2/2)100% (1/1)
access$6 (): int 100% (1/1)100% (2/2)100% (1/1)
buildPath (String, String): String 100% (1/1)100% (12/12)100% (1/1)
buildPath (int, Object []): String 100% (1/1)100% (29/29)100% (6/6)
readLock (): Lock 100% (1/1)100% (4/4)100% (1/1)
tokenize (String): String [] 100% (1/1)100% (47/47)100% (7/7)
writeLock (): Lock 100% (1/1)100% (4/4)100% (1/1)
     
class LocalStringPropertySet$1100% (1/1)100% (2/2)81%  (179/220)83%  (23.9/29)
invoke (Object, Method, Object []): Object 100% (1/1)80%  (167/208)81%  (21.9/27)
LocalStringPropertySet$1 (LocalStringPropertySet, Class, Context): void 100% (1/1)100% (12/12)100% (2/2)

1package com.hammurapi.common.concurrent;
2 
3import java.io.BufferedReader;
4import java.io.IOException;
5import java.io.InputStreamReader;
6import java.lang.reflect.InvocationHandler;
7import java.lang.reflect.Method;
8import java.lang.reflect.Proxy;
9import java.net.URL;
10import java.util.ArrayList;
11import java.util.Arrays;
12import java.util.Enumeration;
13import java.util.HashSet;
14import java.util.List;
15import java.util.Set;
16import java.util.concurrent.ExecutorService;
17import java.util.concurrent.locks.Lock;
18import java.util.concurrent.locks.ReadWriteLock;
19import java.util.concurrent.locks.ReentrantReadWriteLock;
20 
21import com.hammurapi.common.Context;
22import com.hammurapi.convert.Converter;
23 
24public class LocalStringPropertySet extends        LocalAbstractPropertySet<String, String> {
25 
26        private static final String SETTER_PREFIX = "set";
27        private static final int SETTER_PREFIX_LENGTH = SETTER_PREFIX.length();
28        private static final String GETTER_PREFIX = "get";
29        private static final int GETTER_PREFIX_LENGTH = GETTER_PREFIX.length();
30        
31        private String separator;
32        private ClassLoader classLoader;
33        private ReadWriteLock lock; 
34        private Set<String> immutableClasses = new HashSet<String>();
35 
36        public LocalStringPropertySet(
37                        ExecutorService executorService,
38                        Converter converter, 
39                        Context context, 
40                        ClassLoader classLoader,
41                        PropertySet<String>... chain) {
42                this(executorService, converter, context, "/", classLoader, chain);
43        }
44        
45        public LocalStringPropertySet(
46                        ExecutorService executorService,
47                        Converter converter, 
48                        Context context,
49                        String separator,
50                        ClassLoader classLoader,
51                        PropertySet<String>... chain) {
52                this(executorService, converter, context, separator, classLoader, new ReentrantReadWriteLock(), chain);
53                this.separator = separator;
54                this.classLoader = classLoader==null ? getClass().getClassLoader() : classLoader;
55        }
56 
57        protected LocalStringPropertySet(
58                        ExecutorService executorService,
59                        Converter converter, 
60                        Context context,
61                        String separator,
62                        ClassLoader classLoader,
63                        ReadWriteLock lock,
64                        PropertySet<String>... chain) {
65                super(executorService, converter, context, chain);
66                this.separator = separator;
67                this.classLoader = classLoader==null ? getClass().getClassLoader() : classLoader;
68                try {
69                        Enumeration<URL> immutableResources = this.classLoader.getResources("META-INF/services/"+Immutable.class.getName());
70                        while (immutableResources.hasMoreElements()) {
71                                BufferedReader br = new BufferedReader(new InputStreamReader(immutableResources.nextElement().openStream()));
72                                String l;
73                                while ((l=br.readLine())!=null) {
74                                        immutableClasses.add(l.trim());
75                                }
76                        }
77                } catch (IOException e) {
78                        throw new PropertySetException("Cannot load list of immutable classes: "+e, e); 
79                }
80                this.lock = lock; 
81        }
82 
83        @Override
84        protected String buildPath(int startIdx, Object... elements) {
85                StringBuilder sb = new StringBuilder();
86                for (int i=startIdx; i < elements.length; ++i) {
87                        if (i>startIdx) {
88                                sb.append(separator);
89                        }
90                        sb.append(elements[i]);
91                }
92                return sb.toString();
93        }
94 
95        @Override
96        protected String buildPath(String prefix, Object... elements) {
97                StringBuilder sb = new StringBuilder(prefix);
98                for (int i=0; i < elements.length; ++i) {
99                        sb.append(separator);
100                        sb.append(elements[i]);
101                }
102                return sb.toString();
103        }
104 
105        @Override
106        protected String buildPath(String prefix, String suffix) {
107                return prefix+separator+suffix;
108        }
109 
110        @Override
111        protected String[] tokenize(String path) {
112                List<String> ret = new ArrayList<String>();
113                for (int idx = path.indexOf(separator); idx!=-1; idx = path.indexOf(separator)) {
114                        ret.add(path.substring(0, idx));
115                        path = path.substring(idx+separator.length());
116                }
117                if (!path.isEmpty()) {
118                        ret.add(path);
119                }
120                return ret.toArray(new String[ret.size()]);
121        }
122 
123        @Override
124        public <T> T getAdapter(final Class<T> targetType, final Context context) {
125                if (targetType.isInterface()) {
126                        InvocationHandler invocationHandler = new InvocationHandler() {
127 
128                                @Override
129                                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
130                                        if (method.getDeclaringClass().equals(targetType)) {
131                                                Class<?>[] parameterTypes = method.getParameterTypes();
132                                                Class<?> returnType = method.getReturnType();
133                                                String name = method.getName();
134                                                if (name.startsWith(GETTER_PREFIX) && name.length()>GETTER_PREFIX.length() && parameterTypes.length==0 && !void.class.equals(returnType)) { // Getters
135                                                        String firstChar = name.substring(GETTER_PREFIX_LENGTH, GETTER_PREFIX_LENGTH+1).toLowerCase();
136                                                        String pName = name.length()>GETTER_PREFIX.length()+1 ? firstChar + name.substring(GETTER_PREFIX.length()+1) : firstChar;
137                                                        Object ret = get(pName, returnType);
138                                                        if (ret==null || returnType.isInstance(ret)) {
139                                                                return ret;
140                                                        }
141                                                        Object cRet = converter.convert(ret, returnType, context);
142                                                        if (cRet==null) {
143                                                                throw new PropertySetException("Cannot convert from "+ret+" to "+returnType);
144                                                        }
145                                                        return cRet;
146                                                }
147                                                
148                                                if (name.startsWith(SETTER_PREFIX) && name.length()>SETTER_PREFIX.length() && parameterTypes.length==1 && void.class.equals(returnType)) { // Setters
149                                                        String firstChar = name.substring(SETTER_PREFIX_LENGTH, SETTER_PREFIX_LENGTH+1).toLowerCase();
150                                                        String pName = name.length()>SETTER_PREFIX.length()+1 ? firstChar + name.substring(SETTER_PREFIX.length()+1) : firstChar;
151                                                        set(pName, args[0]);
152                                                        return null;
153                                                } 
154                                                
155                                                // Invoke invocable
156                                                Object ret = LocalStringPropertySet.this.invoke(name, args);
157                                                if (ret==null || returnType.isInstance(ret)) {
158                                                        return ret;
159                                                }
160                                                Object cRet = converter.convert(ret, returnType, context);
161                                                if (cRet==null) {
162                                                        throw new PropertySetException("Cannot convert from "+ret+" to "+returnType);
163                                                }
164                                                return cRet;
165                                        } 
166                                        // Object methods.
167                                        return method.invoke(proxy, args);
168                                }
169                                
170                        };
171                        return (T) Proxy.newProxyInstance(classLoader, new Class[] {targetType}, invocationHandler);
172                }
173                
174                return null;
175        }
176        
177        @Override
178        protected <T> T version(T source) {
179                if (source==null) {
180                        return source;
181                }
182                Class<? extends Object> sourceClass = source.getClass();
183                if (immutableClasses.contains(sourceClass.getName())) {
184                        return source;
185                }
186                if (sourceClass.getAnnotation(Immutable.class)!=null) {
187                        return source;
188                }
189                Versionable<T> v = converter.convert(source, Versionable.class, context);
190                if (v!=null) {
191                        return v.createVersion();
192                }
193                if (source instanceof Cloneable) {
194                        try {
195                                return (T) sourceClass.getMethod("clone").invoke(sourceClass);
196                        } catch (Exception e) {
197                                throw new PropertySetException("Cannot version "+source+" by cloning");
198                        }
199                }
200                
201                return source; // Not immutable, not versionable, not cloneable - return AS IS.
202        }
203 
204        @Override
205        protected AbstractPropertySet<String, String> newInstance(String key) {
206                PropertySet<String>[] subChain = Arrays.copyOf(shadows, shadows.length);
207                for (int i=0; i<subChain.length; ++i) {
208                        subChain[i] = new StringSubSet(shadows[i], key, separator);
209                }
210                return new LocalStringPropertySet(
211                                executorService, 
212                                converter, 
213                                context, 
214                                separator, 
215                                classLoader, 
216                                lock, 
217                                subChain);
218        }
219 
220        @Override
221        public Lock readLock() {
222                return lock.readLock();
223        }
224        
225        @Override
226        public Lock writeLock() {
227                return lock.writeLock();
228        }
229}

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