View Javadoc

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 }