Coverage Report - org.apache.tapestry.listener.ListenerMapSourceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ListenerMapSourceImpl
0%
0/48
0%
0/26
2
ListenerMapSourceImpl$1
N/A
N/A
2
ListenerMapSourceImpl$ParameterCountComparator
0%
0/4
N/A
2
 
 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 org.apache.hivemind.util.Defense;
 18  
 import org.apache.tapestry.IPage;
 19  
 import org.apache.tapestry.engine.ILink;
 20  
 import org.apache.tapestry.event.ResetEventListener;
 21  
 
 22  
 import java.lang.reflect.Method;
 23  
 import java.lang.reflect.Modifier;
 24  
 import java.util.*;
 25  
 
 26  
 /**
 27  
  * @author Howard M. Lewis Ship
 28  
  * @since 4.0
 29  
  */
 30  0
 public class ListenerMapSourceImpl implements ListenerMapSource, ResetEventListener
 31  
 {
 32  
 
 33  
     /**
 34  
      * Sorts {@link Method}s into descending order by parameter count.
 35  
      */
 36  
 
 37  0
     private static class ParameterCountComparator implements Comparator
 38  
     {
 39  
 
 40  
         public int compare(Object o1, Object o2)
 41  
         {
 42  0
             Method m1 = (Method) o1;
 43  0
             Method m2 = (Method) o2;
 44  
 
 45  0
             return m2.getParameterTypes().length
 46  
                     - m1.getParameterTypes().length;
 47  
         }
 48  
 
 49  
     }
 50  
 
 51  
     /**
 52  
      * Keyed on Class, value is a Map. The inner Map is an invoker map ... keyed
 53  
      * on listener method name, value is
 54  
      * {@link org.apache.tapestry.listener.ListenerMethodInvoker}.
 55  
      */
 56  
 
 57  0
     private final Map _classToInvokerMap = new HashMap();
 58  
 
 59  
     public ListenerMap getListenerMapForObject(Object object)
 60  
     {
 61  0
         Defense.notNull(object, "object");
 62  
 
 63  0
         Class objectClass = object.getClass();
 64  
 
 65  0
         Map invokerMap = findInvokerMap(objectClass);
 66  
 
 67  0
         return new ListenerMapImpl(object, invokerMap);
 68  
     }
 69  
 
 70  
     public synchronized void resetEventDidOccur()
 71  
     {
 72  0
         _classToInvokerMap.clear();
 73  0
     }
 74  
 
 75  
     private synchronized Map findInvokerMap(Class targetClass)
 76  
     {
 77  0
         Map result = (Map) _classToInvokerMap.get(targetClass);
 78  
 
 79  0
         if (result == null)
 80  
         {
 81  0
             result = buildInvokerMapForClass(targetClass);
 82  0
             _classToInvokerMap.put(targetClass, result);
 83  
         }
 84  
 
 85  0
         return result;
 86  
     }
 87  
 
 88  
     private Map buildInvokerMapForClass(Class targetClass)
 89  
     {
 90  
         // map, keyed on method name, value is List of Method
 91  
         // only methods that return void, return String, or return
 92  
         // something assignable to IPage are kept.
 93  
 
 94  0
         Map map = new HashMap();
 95  
 
 96  0
         Method[] methods = targetClass.getMethods();
 97  
 
 98  
         // Sort all the arrays, just once, and the methods will be
 99  
         // added to the individual lists in the correct order
 100  
         // (descending by parameter count).
 101  
 
 102  0
         Arrays.sort(methods, new ParameterCountComparator());
 103  
 
 104  0
         for(int i = 0; i < methods.length; i++)
 105  
         {
 106  0
             Method m = methods[i];
 107  
 
 108  0
             if (!isAcceptibleListenerMethodReturnType(m)) continue;
 109  
 
 110  0
             if (Modifier.isStatic(m.getModifiers())) continue;
 111  
 
 112  0
             String name = m.getName();
 113  
 
 114  0
             addMethodToMappedList(map, m, name);
 115  
         }
 116  
 
 117  0
         return convertMethodListMapToInvokerMap(map);
 118  
     }
 119  
 
 120  
     boolean isAcceptibleListenerMethodReturnType(Method m)
 121  
     {
 122  0
         Class returnType = m.getReturnType();
 123  
 
 124  0
         if (returnType == void.class || returnType == String.class)
 125  0
             return true;
 126  
 
 127  0
         return IPage.class.isAssignableFrom(returnType)
 128  
                 || ILink.class.isAssignableFrom(returnType);
 129  
     }
 130  
 
 131  
     private Map convertMethodListMapToInvokerMap(Map map)
 132  
     {
 133  0
         Map result = new HashMap();
 134  
 
 135  0
         Iterator i = map.entrySet().iterator();
 136  0
         while(i.hasNext())
 137  
         {
 138  0
             Map.Entry e = (Map.Entry) i.next();
 139  
 
 140  0
             String name = (String) e.getKey();
 141  0
             List methodList = (List) e.getValue();
 142  
 
 143  0
             Method[] methods = convertMethodListToArray(methodList);
 144  
 
 145  0
             ListenerMethodInvoker invoker = createListenerMethodInvoker(name,
 146  
                     methods);
 147  
 
 148  0
             result.put(name, invoker);
 149  0
         }
 150  
 
 151  0
         return result;
 152  
     }
 153  
 
 154  
     /**
 155  
      * This implementation returns a new {@link ListenerMethodInvoker}.
 156  
      * Subclasses can override to provide their own implementation.
 157  
      */
 158  
 
 159  
     protected ListenerMethodInvoker createListenerMethodInvoker(String name,
 160  
             Method[] methods)
 161  
     {
 162  0
         return new ListenerMethodInvokerImpl(name, methods);
 163  
     }
 164  
 
 165  
     private Method[] convertMethodListToArray(List methodList)
 166  
     {
 167  0
         int size = methodList.size();
 168  0
         Method[] result = new Method[size];
 169  
 
 170  0
         return (Method[]) methodList.toArray(result);
 171  
     }
 172  
 
 173  
     private void addMethodToMappedList(Map map, Method m, String name)
 174  
     {
 175  0
         List l = (List) map.get(name);
 176  
 
 177  0
         if (l == null)
 178  
         {
 179  0
             l = new ArrayList();
 180  0
             map.put(name, l);
 181  
         }
 182  
 
 183  0
         l.add(m);
 184  0
     }
 185  
 }