KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > listener > ListenerMapSourceImpl


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 JavaDoc;
18 import java.lang.reflect.Modifier JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Arrays JavaDoc;
21 import java.util.Comparator JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
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 JavaDoc
42     {
43         public int compare(Object JavaDoc o1, Object JavaDoc o2)
44         {
45             Method JavaDoc m1 = (Method JavaDoc) o1;
46             Method JavaDoc m2 = (Method JavaDoc) o2;
47
48             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 JavaDoc _classToInvokerMap = new HashMap JavaDoc();
59
60     public ListenerMap getListenerMapForObject(Object JavaDoc object)
61     {
62         Defense.notNull(object, "object");
63
64         Class JavaDoc objectClass = object.getClass();
65
66         Map JavaDoc invokerMap = findInvokerMap(objectClass);
67
68         return new ListenerMapImpl(object, invokerMap);
69     }
70
71     public synchronized void resetEventDidOccur()
72     {
73         _classToInvokerMap.clear();
74     }
75
76     private synchronized Map JavaDoc findInvokerMap(Class JavaDoc targetClass)
77     {
78         Map JavaDoc result = (Map JavaDoc) _classToInvokerMap.get(targetClass);
79
80         if (result == null)
81         {
82             result = buildInvokerMapForClass(targetClass);
83             _classToInvokerMap.put(targetClass, result);
84         }
85
86         return result;
87     }
88
89     private Map JavaDoc buildInvokerMapForClass(Class JavaDoc 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         Map JavaDoc map = new HashMap JavaDoc();
96
97         Method JavaDoc[] 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         Arrays.sort(methods, new ParameterCountComparator());
104
105         for (int i = 0; i < methods.length; i++)
106         {
107             Method JavaDoc m = methods[i];
108
109             if (!isAcceptibleListenerMethodReturnType(m))
110                 continue;
111
112             if (Modifier.isStatic(m.getModifiers()))
113                 continue;
114
115             String JavaDoc name = m.getName();
116
117             addMethodToMappedList(map, m, name);
118         }
119
120         return convertMethodListMapToInvokerMap(map);
121     }
122
123     boolean isAcceptibleListenerMethodReturnType(Method JavaDoc m)
124     {
125         Class JavaDoc returnType = m.getReturnType();
126
127         if (returnType == void.class || returnType == String JavaDoc.class)
128             return true;
129
130         return IPage.class.isAssignableFrom(returnType);
131     }
132
133     private Map JavaDoc convertMethodListMapToInvokerMap(Map JavaDoc map)
134     {
135         Map JavaDoc result = new HashMap JavaDoc();
136
137         Iterator JavaDoc i = map.entrySet().iterator();
138         while (i.hasNext())
139         {
140             Map.Entry JavaDoc e = (Map.Entry JavaDoc) i.next();
141
142             String JavaDoc name = (String JavaDoc) e.getKey();
143             List JavaDoc methodList = (List JavaDoc) e.getValue();
144
145             Method JavaDoc[] methods = convertMethodListToArray(methodList);
146
147             ListenerMethodInvoker invoker = createListenerMethodInvoker(name, methods);
148
149             result.put(name, invoker);
150         }
151
152         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     protected ListenerMethodInvokerImpl createListenerMethodInvoker(String JavaDoc name, Method JavaDoc[] methods)
162     {
163         return new ListenerMethodInvokerImpl(name, methods);
164     }
165
166     private Method JavaDoc[] convertMethodListToArray(List JavaDoc methodList)
167     {
168         int size = methodList.size();
169         Method JavaDoc[] result = new Method JavaDoc[size];
170
171         return (Method JavaDoc[]) methodList.toArray(result);
172     }
173
174     private void addMethodToMappedList(Map JavaDoc map, Method JavaDoc m, String JavaDoc name)
175     {
176         List JavaDoc l = (List JavaDoc) map.get(name);
177
178         if (l == null)
179         {
180             l = new ArrayList JavaDoc();
181             map.put(name, l);
182         }
183
184         l.add(m);
185     }
186 }
Popular Tags