Source Code Cross Referenced for FunctorProxy.java in  » Development » jga-Generic-Algorithms » net » sf » jga » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jga Generic Algorithms » net.sf.jga.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // ============================================================================
002:        // $Id: FunctorProxy.java,v 1.7 2006/11/30 05:06:10 davidahall Exp $
003:        // Copyright (c) 2005  David A. Hall
004:        // ============================================================================
005:        // The contents of this file are subject to the Common Development and
006:        // Distribution License (CDDL), Version 1.0 (the License); you may not use this 
007:        // file except in compliance with the License.  You should have received a copy
008:        // of the the License along with this file: if not, a copy of the License is 
009:        // available from Sun Microsystems, Inc.
010:        //
011:        // http://www.sun.com/cddl/cddl.html
012:        //
013:        // From time to time, the license steward (initially Sun Microsystems, Inc.) may
014:        // publish revised and/or new versions of the License.  You may not use,  
015:        // distribute, or otherwise make this file available under subsequent versions 
016:        // of the License.
017:        // 
018:        // Alternatively, the contents of this file may be used under the terms of the 
019:        // GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
020:        // case the provisions of the LGPL are applicable instead of those above. If you 
021:        // wish to allow use of your version of this file only under the terms of the 
022:        // LGPL, and not to allow others to use your version of this file under the 
023:        // terms of the CDDL, indicate your decision by deleting the provisions above 
024:        // and replace them with the notice and other provisions required by the LGPL. 
025:        // If you do not delete the provisions above, a recipient may use your version 
026:        // of this file under the terms of either the CDDL or the LGPL.
027:        // 
028:        // This library is distributed in the hope that it will be useful,
029:        // but WITHOUT ANY WARRANTY; without even the implied warranty of
030:        // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
031:        // ============================================================================
032:
033:        package net.sf.jga.swing;
034:
035:        import java.awt.Event;
036:        import java.io.Serializable;
037:        import java.lang.ref.Reference;
038:        import java.lang.ref.WeakReference;
039:        import java.lang.reflect.InvocationHandler;
040:        import java.lang.reflect.InvocationTargetException;
041:        import java.lang.reflect.Method;
042:        import java.lang.reflect.Proxy;
043:        import java.util.Collections;
044:        import java.util.EventListener;
045:        import java.util.HashMap;
046:        import java.util.HashSet;
047:        import java.util.Iterator;
048:        import java.util.Map;
049:        import java.util.Set;
050:        import java.util.WeakHashMap;
051:        import net.sf.jga.algorithms.Filter;
052:        import net.sf.jga.fn.BinaryFunctor;
053:        import net.sf.jga.fn.UnaryFunctor;
054:        import net.sf.jga.parser.GenericParser;
055:        import net.sf.jga.parser.ParseException;
056:        import net.sf.jga.parser.UncheckedParseException;
057:
058:        /**
059:         * Factory that builds Proxy objects that map Functors to event notification methods.
060:         * Using this proxy is a two step process: first build the proxy instance calling
061:         * <tt>makeListenerFor</tt> or <tt>newProxyInstance</tt>; second, register the
062:         * desired functors with the various registration methods.
063:         * <p>
064:         * Copyright &copy; 2005  David A. Hall
065:         */
066:
067:        public class FunctorProxy {
068:
069:            /**
070:             * Manufactures a Proxy that can listen to any/all events that the given
071:             * object may fire.  The generated Proxy's invocation handler will be an
072:             * instance FunctorInvocationHandler.
073:             */
074:            static public Proxy makeListenerFor(Object obj) {
075:                return newProxyInstance(obj.getClass().getClassLoader(),
076:                        identifyListeners(obj.getClass()));
077:            }
078:
079:            /**
080:             * Returns an instance of a proxy class for the specified interfaces that dispatches
081:             * method invocations to functors registed via a FunctorInvocationHandler.
082:             */
083:            static public Proxy newProxyInstance(ClassLoader loader,
084:                    Class[] interfaces) {
085:                return (Proxy) Proxy.newProxyInstance(loader, interfaces,
086:                        new FunctorInvocationHandler(interfaces));
087:            }
088:
089:            // ------------
090:            // registration
091:            // ------------
092:
093:            /**
094:             * Registers the functor described by the given expression, to be invoked by the proxy
095:             * when a method with the given method is called.  If the proxy supports more than one
096:             * method with this name, then which one will be invoked is undefined.
097:             *
098:             * @throws NoSuchMethodException if no method with the given name is found
099:             * @throws ParseException if the expression cannot be parsed 
100:             * @throws ClassCastException if the given proxy's handler is not a FunctorInvocationHandler
101:             */
102:            static public void register(Proxy proxy, String methodName,
103:                    String expression) throws ParseException,
104:                    NoSuchMethodException {
105:                getFunctorInvocationHandler(proxy).register(methodName,
106:                        expression);
107:            }
108:
109:            /**
110:             * Registers the given functor to be invoked by the proxy when a method with the given
111:             * method is called.  If the proxy supports more than one method with this name, then
112:             * which one will be invoked is undefined.
113:             *
114:             * @throws NoSuchMethodException if no method with the given name is found
115:             * @throws ClassCastException if the given proxy's handler is not a FunctorInvocationHandler
116:             */
117:            static public void register(Proxy proxy, String methodName,
118:                    UnaryFunctor functor) throws NoSuchMethodException {
119:                getFunctorInvocationHandler(proxy)
120:                        .register(methodName, functor);
121:            }
122:
123:            /**
124:             * Registers the given functor to be invoked by the proxy when the given method is called.
125:             * @throws ClassCastException if the given proxy's handler is not a FunctorInvocationHandler
126:             */
127:            static public void register(Proxy proxy, Method method,
128:                    UnaryFunctor functor) {
129:                getFunctorInvocationHandler(proxy).register(method, functor);
130:            }
131:
132:            /**
133:             * Registers a functor to be evaluated when the given method is invoked.
134:             * @throws IllegalArgumentException if the proxy does not implement the listenerClass
135:             * @throws NoSuchMethodException if the proxy does not have a method with the given
136:             *    name that takes an argument of class eventClass
137:             * @throws ClassCastException if the given proxy's handler is not a FunctorInvocationHandler
138:             */
139:            static public void register(Proxy proxy, Class listenerClass,
140:                    Class eventClass, String methodName, UnaryFunctor functor)
141:                    throws NoSuchMethodException, IllegalArgumentException {
142:                if (listenerClass.isInstance(proxy)) {
143:                    Method m = listenerClass.getMethod(methodName,
144:                            new Class[] { eventClass });
145:                    getFunctorInvocationHandler(proxy).register(m, functor);
146:                    return;
147:                }
148:
149:                throw new IllegalArgumentException("This does not implement "
150:                        + listenerClass.getName());
151:            }
152:
153:            // ----------------------
154:            // implementation details
155:            // ----------------------
156:
157:            // Maps 'Listenee' classes to the arrays of Listener interfaces they support
158:            static private Map<Class<?>, WeakReference> proxyClasses = Collections
159:                    .synchronizedMap(new WeakHashMap<Class<?>, WeakReference>());
160:
161:            // A predicate that is true when a method is an add${FOO}Listener
162:            static private final UnaryFunctor<Method, Boolean> isAddListenerMethod = GenericParser
163:                    .parse("x.getName().matches(\"^add.*Listener$\")",
164:                            Method.class, Boolean.class);
165:
166:            /**
167:             * Returns a list of the ${FOO}Listener interfaces which an object of Class clasz
168:             * may fire events (ie, the Listeners which such an object can add). 
169:             */
170:            static private Class[] identifyListeners(Class<?> clasz) {
171:                synchronized (proxyClasses) {
172:                    // See if we've already generated such a list: if so, return it.
173:                    Object value = proxyClasses.get(clasz);
174:                    if (value instanceof  Reference) {
175:                        return (Class[]) ((Reference) value).get();
176:                    }
177:
178:                    // Otherwise, we'll need to build the list.  For now, we can find all methods
179:                    // whose names are of the form "add${FOO}Listener", and that take a single
180:                    // argument of a type derived from EventListener.
181:                    Set<Class<?>> interfaceSet = new HashSet<Class<?>>();
182:
183:                    //          for(Method m : Filter.filter(clasz.getMethods(), isAddListenerMethod)) {
184:                    Iterator<Method> iter = Filter.filter(clasz.getMethods(),
185:                            isAddListenerMethod).iterator();
186:                    while (iter.hasNext()) {
187:                        Method m = iter.next();
188:                        Class[] argtypes = m.getParameterTypes();
189:                        if (argtypes.length == 1) {
190:                            Class c = m.getParameterTypes()[0];
191:                            if (EventListener.class.isAssignableFrom(c)) {
192:                                interfaceSet.add(c);
193:                            }
194:                        }
195:                    }
196:
197:                    // Save ourselves the work next time around.
198:                    Class[] interfaceArray = interfaceSet
199:                            .toArray(new Class[interfaceSet.size()]);
200:                    proxyClasses.put(clasz, new WeakReference(interfaceArray));
201:                    return interfaceArray;
202:                }
203:            }
204:
205:            /**
206:             * @returns the FunctorInvocationHandler associated with the given proxy
207:             * @throws ClassCastException if the given proxy's handler is not a FunctorInvocationHandler
208:             */
209:            static private FunctorInvocationHandler getFunctorInvocationHandler(
210:                    Proxy proxy) {
211:                return (FunctorInvocationHandler) Proxy
212:                        .getInvocationHandler(proxy);
213:            }
214:
215:            /**
216:             * The InvocationHandler for FunctorProxy instances.  This handler allows individual
217:             * methods to be mapped to Functors of the form UnaryFunctor<Event>.  When the method
218:             * (which must be an event notification method of one of the listener interfaces that
219:             * the proxy object implements) is invoked, the event is passed to the appropriate
220:             * functor for evaluation.
221:             */
222:            static public class FunctorInvocationHandler implements 
223:                    InvocationHandler, Serializable {
224:
225:                static final long serialVersionUID = -6537167128759416788L;
226:
227:                // The interfaces for which this handler can route method invocations
228:                private Class[] _interfaces;
229:
230:                // Maps methods to the functors that will be invoked
231:                private Map<Method, UnaryFunctor> _functors = new HashMap<Method, UnaryFunctor>();
232:
233:                // Functor that returns true if a given method has the given name
234:                static private final BinaryFunctor<Method, String, Boolean> isNameEq = GenericParser
235:                        .parse("x.getName() == y", Method.class, String.class,
236:                                Boolean.class);
237:
238:                private FunctorInvocationHandler(Class[] interfaces) {
239:                    _interfaces = interfaces;
240:                }
241:
242:                /**
243:                 * Returns the first method found with the given name
244:                 * @throws NoSuchMethodException if no method with the given name is found
245:                 */
246:                private Method getMethod(String name)
247:                        throws NoSuchMethodException {
248:                    UnaryFunctor<Method, Boolean> hasGivenName = isNameEq
249:                            .bind2nd(name);
250:
251:                    // Loop through the interfaces that this handler supports to find
252:                    // the one with the named method, and return the method if found
253:
254:                    //          for (Class iface : _interfaces) 
255:                    for (int i = 0; i < _interfaces.length; ++i) {
256:                        Class iface = _interfaces[i];
257:
258:                        //              for(Method method : Iterables.filter(iface.getMethods(), hasGivenName))
259:                        Iterator<Method> iter = Filter.filter(
260:                                iface.getMethods(), hasGivenName).iterator();
261:                        if (iter.hasNext()) {
262:                            return iter.next();
263:                        }
264:                    }
265:
266:                    throw new NoSuchMethodException(name);
267:                }
268:
269:                /**
270:                 * Registers the functor described by the given expression, to be invoked a
271:                 * method with the given method is called.  If this handler has more than one
272:                 * method with this name, then which one will be invoked is undefined.
273:                 *
274:                 * @throws NoSuchMethodException if no method with the given name is found
275:                 * @throws ParseException if the expression cannot be parsed 
276:                 */
277:                private void register(String methodName, String expression)
278:                        throws ParseException, NoSuchMethodException {
279:                    Method m = getMethod(methodName);
280:                    UnaryFunctor fn = GenericParser.parse(expression, m
281:                            .getParameterTypes()[0], m.getReturnType());
282:
283:                    register(m, fn);
284:                }
285:
286:                /**
287:                 * Registers the given functor, to be invoked a method with the given method
288:                 * is called.  If this handler has more than one method with this name, then
289:                 * which one will be invoked is undefined.
290:                 *
291:                 * @throws NoSuchMethodException if no method with the given name is found
292:                 */
293:                private void register(String methodName, UnaryFunctor functor)
294:                        throws NoSuchMethodException {
295:                    Method m = getMethod(methodName);
296:                    register(m, functor);
297:                }
298:
299:                /**
300:                 * Registers the given functor, to be invoked when the given method is called.
301:                 */
302:                private void register(Method method, UnaryFunctor functor) {
303:                    _functors.put(method, functor);
304:                }
305:
306:                /**
307:                 */
308:                private void unregister(Method method) {
309:                    _functors.remove(method);
310:                }
311:
312:                /**
313:                 */
314:                private UnaryFunctor getFunctor(Method method) {
315:                    return _functors.get(method);
316:                }
317:
318:                // --------------------------------
319:                // InvocationHandler Implementation 
320:                // --------------------------------
321:
322:                /**
323:                 */
324:                public Object invoke(Object object, Method method,
325:                        Object[] objectArray) throws Throwable {
326:                    UnaryFunctor functor = getFunctor(method);
327:                    if (functor != null) {
328:                        functor.fn(objectArray[0]);
329:                    }
330:
331:                    return null;
332:                }
333:            }
334:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.