Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 186   Methods: 10
NCLOC: 105   Classes: 2
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ListenerMapSourceImpl.java 100% 97.9% 90% 97.2%
coverage coverage
 1    // Copyright 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry.listener;
 16   
 17    import java.lang.reflect.Method;
 18    import java.lang.reflect.Modifier;
 19    import java.util.ArrayList;
 20    import java.util.Arrays;
 21    import java.util.Comparator;
 22    import java.util.HashMap;
 23    import java.util.Iterator;
 24    import java.util.List;
 25    import java.util.Map;
 26   
 27    import org.apache.hivemind.util.Defense;
 28    import org.apache.tapestry.IPage;
 29    import org.apache.tapestry.event.ResetEventListener;
 30   
 31    /**
 32    * @author Howard M. Lewis Ship
 33    * @since 4.0
 34    */
 35    public class ListenerMapSourceImpl implements ListenerMapSource, ResetEventListener
 36    {
 37    /**
 38    * Sorts {@link Method}s into descending order by parameter count.
 39    */
 40   
 41    private static class ParameterCountComparator implements Comparator
 42    {
 43  9809 public int compare(Object o1, Object o2)
 44    {
 45  9809 Method m1 = (Method) o1;
 46  9809 Method m2 = (Method) o2;
 47   
 48  9809 return m2.getParameterTypes().length - m1.getParameterTypes().length;
 49    }
 50   
 51    }
 52   
 53    /**
 54    * Keyed on Class, value is a Map. The inner Map is an invoker map ... keyed on listener method
 55    * name, value is {@link org.apache.tapestry.listener.ListenerMethodInvoker}.
 56    */
 57   
 58    private final Map _classToInvokerMap = new HashMap();
 59   
 60  34 public ListenerMap getListenerMapForObject(Object object)
 61    {
 62  34 Defense.notNull(object, "object");
 63   
 64  34 Class objectClass = object.getClass();
 65   
 66  34 Map invokerMap = findInvokerMap(objectClass);
 67   
 68  34 return new ListenerMapImpl(object, invokerMap);
 69    }
 70   
 71  0 public synchronized void resetEventDidOccur()
 72    {
 73  0 _classToInvokerMap.clear();
 74    }
 75   
 76  34 private synchronized Map findInvokerMap(Class targetClass)
 77    {
 78  34 Map result = (Map) _classToInvokerMap.get(targetClass);
 79   
 80  34 if (result == null)
 81    {
 82  32 result = buildInvokerMapForClass(targetClass);
 83  32 _classToInvokerMap.put(targetClass, result);
 84    }
 85   
 86  34 return result;
 87    }
 88   
 89  32 private Map buildInvokerMapForClass(Class targetClass)
 90    {
 91    // map, keyed on method name, value is List of Method
 92    // only methods that return void, return String, or return
 93    // something assignable to IPage are kept.
 94   
 95  32 Map map = new HashMap();
 96   
 97  32 Method[] methods = targetClass.getMethods();
 98   
 99    // Sort all the arrays, just once, and the methods will be
 100    // added to the individual lists in the correct order
 101    // (descending by parameter count).
 102   
 103  32 Arrays.sort(methods, new ParameterCountComparator());
 104   
 105  32 for (int i = 0; i < methods.length; i++)
 106    {
 107  2219 Method m = methods[i];
 108   
 109  2219 if (!isAcceptibleListenerMethodReturnType(m))
 110  754 continue;
 111   
 112  1465 if (Modifier.isStatic(m.getModifiers()))
 113  8 continue;
 114   
 115  1457 String name = m.getName();
 116   
 117  1457 addMethodToMappedList(map, m, name);
 118    }
 119   
 120  32 return convertMethodListMapToInvokerMap(map);
 121    }
 122   
 123  2224 boolean isAcceptibleListenerMethodReturnType(Method m)
 124    {
 125  2224 Class returnType = m.getReturnType();
 126   
 127  2224 if (returnType == void.class || returnType == String.class)
 128  1425 return true;
 129   
 130  799 return IPage.class.isAssignableFrom(returnType);
 131    }
 132   
 133  32 private Map convertMethodListMapToInvokerMap(Map map)
 134    {
 135  32 Map result = new HashMap();
 136   
 137  32 Iterator i = map.entrySet().iterator();
 138  32 while (i.hasNext())
 139    {
 140  1316 Map.Entry e = (Map.Entry) i.next();
 141   
 142  1316 String name = (String) e.getKey();
 143  1316 List methodList = (List) e.getValue();
 144   
 145  1316 Method[] methods = convertMethodListToArray(methodList);
 146   
 147  1316 ListenerMethodInvoker invoker = createListenerMethodInvoker(name, methods);
 148   
 149  1316 result.put(name, invoker);
 150    }
 151   
 152  32 return result;
 153    }
 154   
 155    /**
 156    * This implementation returns a new
 157    * {@link org.apache.tapestry.listener.ListenerMethodInvokerImpl}. Subclasses can override to
 158    * provide their own implementation.
 159    */
 160   
 161  1316 protected ListenerMethodInvokerImpl createListenerMethodInvoker(String name, Method[] methods)
 162    {
 163  1316 return new ListenerMethodInvokerImpl(name, methods);
 164    }
 165   
 166  1316 private Method[] convertMethodListToArray(List methodList)
 167    {
 168  1316 int size = methodList.size();
 169  1316 Method[] result = new Method[size];
 170   
 171  1316 return (Method[]) methodList.toArray(result);
 172    }
 173   
 174  1457 private void addMethodToMappedList(Map map, Method m, String name)
 175    {
 176  1457 List l = (List) map.get(name);
 177   
 178  1457 if (l == null)
 179    {
 180  1316 l = new ArrayList();
 181  1316 map.put(name, l);
 182    }
 183   
 184  1457 l.add(m);
 185    }
 186    }