VisitorConverter.java

biz/hammurapi/util/VisitorConverter.java

Violations

Inspector Message Severity Location
Java Inspector 048 Copyrights information should be present in each file. 1
Java Inspector 049 Use a Collection instead of arrays Object[] 2 48:23
Java Inspector 089 Undocumented top level type 2 10:1
Java Inspector 089 Undocumented parameter object 2 36:9
Java Inspector 089 Javadoc contains tag for non-existent parameter target 2 36:9
Java Inspector 089 Undocumented method 2 80:25
Java Inspector 089 Undocumented method 2 107:25
Java Inspector 089 Undocumented method 2 121:25

Source code

1package biz.hammurapi.util;
2
3import java.lang.reflect.Method;
4import java.lang.reflect.Modifier;
5import java.lang.reflect.UndeclaredThrowableException;
6import java.util.ArrayList;
7import java.util.Iterator;
8import java.util.List;
9
10public class VisitorConverter {
11
12 /**
13 * Name of leave method.
14 */
15 public static final String LEAVE = "leave";
16
17 /**
18 * Name of visit method.
19 */
20 public static final String VISIT = "visit";
21
22 /**
23 * Converts object to visitor.
24 * If visitor is instance of <code>Visitor</code>, then this method returns
25 * object unchanged. Otherwise it introspects object for public
26 * <boolean>visit()</boolean> and <boolean>leave()</boolean> methods
27 * with a single argument returning boolean or void. If such methods are found
28 * they are made accessible in order to enable invocation of methods declared in
29 * anonymous and local classes. This method returns an anonymous visitor or polite
30 * visitor (if there are leave() methods). This anonymous (polite) visitor
31 * dispatches invocations to visit() and leave() methods with compatible types.
32 * @param target Object to be converted to visitor
33 * @return Object argument if it already implements visitor, or dispatcher
34 * to object's visit() and leave() methods.
35 */
36 public Visitor convert(final Object object) {
37 if (object == null ) {
38 return null;
39 }
40
41 if (object instanceof Visitor) {
42 return (Visitor) object;
43 }
44
45 final List visitMethods = new ArrayList();
46 final List leaveMethods = new ArrayList();
47
48 Method[] methods = object.getClass().getMethods();
49 for (int i=0; i<methods.length; ++i) {
50 Method method = methods[i];
51 if (Modifier.isPublic(method.getModifiers())
52 && VISIT.equals(method.getName())
53 && method.getParameterTypes().length==1
54 && (void.class.equals(method.getReturnType()) || boolean.class.equals(method.getReturnType()))) {
55
56 if (!method.isAccessible()) {
57 method.setAccessible(true);
58 }
59 visitMethods.add(method);
60 }
61
62 if (Modifier.isPublic(method.getModifiers())
63 && LEAVE.equals(method.getName())
64 && method.getParameterTypes().length==1
65 && void.class.equals(method.getReturnType())) {
66
67 if (!method.isAccessible()) {
68 method.setAccessible(true);
69 }
70 leaveMethods.add(method);
71 }
72 }
73
74 if (visitMethods.isEmpty() && leaveMethods.isEmpty()) {
75 return null;
76 }
77
78 final Visitor dispatcher = new Visitor() {
79
80 public boolean visit(Object target) {
81 Iterator it = visitMethods.iterator();
82 while (it.hasNext()) {
83 Method visitMethod = (Method) it.next();
84 if (visitMethod.getParameterTypes()[0].isInstance(target)) {
85 try {
86 Object ret = visitMethod.invoke(object, new Object[] {target});
87 if (Boolean.FALSE.equals(ret)) {
88 return false;
89 }
90 } catch (Exception e) {
91 throw new UndeclaredThrowableException(e);
92 }
93 }
94 }
95
96 return true;
97 }
98
99 };
100
101 if (leaveMethods.isEmpty()) {
102 return dispatcher;
103 }
104
105 return new PoliteVisitor() {
106
107 public void leave(Object target) {
108 Iterator it = visitMethods.iterator();
109 while (it.hasNext()) {
110 Method visitMethod = (Method) it.next();
111 if (visitMethod.getParameterTypes()[0].isInstance(target)) {
112 try {
113 visitMethod.invoke(object, new Object[] {target});
114 } catch (Exception e) {
115 throw new UndeclaredThrowableException(e);
116 }
117 }
118 }
119 }
120
121 public boolean visit(Object target) {
122 return dispatcher.visit(target);
123 }
124
125 };
126 }
127
128}
129