1
2 package org.onemind.commons.java.pattern;
3
4 import java.lang.reflect.Method;
5 import org.onemind.commons.java.datastructure.InheritableValueMap;
6 import org.onemind.commons.java.lang.reflect.ReflectUtils;
7 /***
8 * An abstract implementation of visitor that is extensible for handling
9 * different kind of object nodes by simple adding more methods. The subclass need to
10 * set up for handlers of node type in the constructor.
11 *
12 * @author TiongHiang Lee (thlee@onemindsoft.org)
13 * @version $Id: DynamicVisitor.java,v 1.2 2004/10/31 16:02:08 thlee Exp $ $Name: $
14 */
15 public abstract class DynamicVisitor
16 {
17
18 /*** the object array class **/
19 private static Class OBJECT_ARRAY_CLASS = new Object[0].getClass();
20
21 /***
22 * The handler
23 * @author TiongHiang Lee (thlee@onemindsoft.org)
24 * @version $Id: DynamicVisitor.java,v 1.2 2004/10/31 16:02:08 thlee Exp $ $Name: $
25 */
26 public static interface NodeHandler
27 {
28
29 /***
30 * Handle node
31 * @param node
32 * @param data
33 */
34 public Object handleNode(Object node, Object[] data) throws Exception;
35 }
36
37 /***
38 * A handler use reflection to invoke given method for visiting
39 */
40 protected class MethodNodeHandler implements NodeHandler
41 {
42
43 /*** the method **/
44 private Method _method;
45
46 /***
47 * Constructor
48 * @param methodName the method name
49 */
50 public MethodNodeHandler(Method method)
51 {
52 _method = method;
53 }
54
55 /***
56 * {@inheritDoc}
57 */
58 public Object handleNode(Object node, Object[] data) throws Exception
59 {
60 Object[] args = {node, data};
61 return _method.invoke(DynamicVisitor.this, args);
62 }
63 }
64
65 /*** contains the handlers for different kind of nodese **/
66 private final InheritableValueMap _handlers = new InheritableValueMap();
67
68 /***
69 * Constructor
70 */
71 public DynamicVisitor()
72 {
73 initNodeHandlers();
74 }
75
76 /***
77 * Initialize the node handlers
78 */
79 protected abstract void initNodeHandlers();
80
81 /***
82 * Add node handler
83 * @param type the type
84 * @param handler the handler
85 */
86 protected void addNodeHandler(Class type, NodeHandler handler)
87 {
88 _handlers.put(type, handler);
89 }
90
91 /***
92 * Add MethodNodeHandler using the given method name
93 * throws RuntimeException if the method cannot be found.
94 * @param type the type
95 * @param methodName the method name
96 */
97 protected void addMethodNodeHandler(Class type, String methodName)
98 {
99 try
100 {
101 Class args[] = {type, new Object[0].getClass()};
102 Method m = ReflectUtils.getMethod(getClass(), methodName, args);
103 _handlers.put(type, new MethodNodeHandler(m));
104 } catch (Exception e)
105 {
106 throw new RuntimeException(e);
107 }
108 }
109
110 /***
111 * The object
112 * @param obj the object
113 * @param args the arguments
114 */
115 public Object visit(Object obj, Object[] args) throws Exception
116 {
117 NodeHandler handler = (NodeHandler) _handlers.resolve(obj.getClass());
118 if (handler != null)
119 {
120 return handler.handleNode(obj, args);
121 } else
122 {
123 throw new IllegalArgumentException("Cannot find handler method for object " + obj);
124 }
125 }
126 }