2
2
3
3
import org .javalite .templator .TemplateException ;
4
4
5
+ import java .lang .reflect .Field ;
6
+ import java .lang .reflect .InvocationTargetException ;
7
+ import java .lang .reflect .Method ;
8
+ import java .util .HashMap ;
5
9
import java .util .List ;
6
10
import java .util .Map ;
7
11
import static org .javalite .common .Inflector .*;
@@ -18,40 +22,98 @@ class ChainedIds {
18
22
this .ids = ids ;
19
23
}
20
24
21
- private Object valueOf (Object obj , String id ) {
22
- try {
23
- if (id .endsWith ("()" )) {
24
- return obj .getClass ().getMethod (id .substring (0 , id .length () - 2 )).invoke (obj );
25
+ private Object valueOf (Object obj , String propertyName ) throws InvocationTargetException , IllegalAccessException {
26
+
27
+ if (propertyName .endsWith ("()" )) {
28
+ return executeMethod (obj , propertyName .substring (0 , propertyName .length () - 2 ), null );
29
+
25
30
}
26
- } catch (Exception e ) {
27
- throw new TemplateException (e );
28
- }
31
+
32
+ Object val = null ;
33
+
34
+ //try map
29
35
if (obj instanceof Map ) {
30
- return ((Map ) obj ).get (id );
36
+ Map objectMap = (Map ) obj ;
37
+ return objectMap .get (propertyName );
38
+ }
39
+
40
+ if (val == null ) {
41
+ //try properties
42
+ val = executeMethod (obj , "get" + capitalize (propertyName ), null );
43
+ if (val != null )
44
+ return val ;
31
45
}
32
- try {
33
- // try generic get method
34
- return obj .getClass ().getMethod ("get" , String .class ).invoke (obj , id );
35
- } catch (Exception e ) {
46
+
47
+
48
+ //try generic get method
49
+ if (val == null ) {
50
+ val = executeMethod (obj , "get" , propertyName );
51
+ if (val != null )
52
+ return val ;
53
+ }
54
+
55
+
56
+ if (val == null ) {
57
+ // try public fields
36
58
try {
37
- // try javabean property
38
- return obj .getClass ().getMethod ( "get" + capitalize ( id )). invoke ( obj );
39
- } catch ( Exception e1 ) {
40
- // try public field
41
- try {
42
- return obj . getClass (). getDeclaredField ( id ). get ( obj );
43
- } catch (Exception e2 ) {
44
- }
59
+ //TODO: optimize the same as methods.
60
+ Field f = obj .getClass ().getDeclaredField ( propertyName );
61
+ val = f . get ( obj );
62
+ if ( val != null )
63
+ return val ;
64
+
65
+ } catch (NoSuchFieldException ignore ) {
66
+ } catch ( IllegalAccessException ignore ) {
45
67
}
46
68
}
47
- return null ;
69
+
70
+ return val ;
71
+ }
72
+
73
+ private ThreadLocal <Map <String , Method >> methodCache = new ThreadLocal <Map <String , Method >>();
74
+
75
+ private Object executeMethod (Object obj , String methodName , String propertyName ) throws InvocationTargetException , IllegalAccessException {
76
+
77
+ //quick hack:
78
+ if (methodCache .get () == null ) {
79
+ methodCache .set (new HashMap <String , Method >());
80
+ }
81
+
82
+
83
+ String key = obj .getClass ().getName () + "#" + methodName ;
84
+ Method m = null ;
85
+
86
+ if (!methodCache .get ().containsKey (key )) {
87
+ try {
88
+ m = propertyName == null ? obj .getClass ().getMethod (methodName ) : obj .getClass ().getMethod (methodName , String .class );
89
+ } catch (NoSuchMethodException e ) {}
90
+
91
+ // if we find a method, we will cache it, if not we will cache null
92
+ methodCache .get ().put (key , m );
93
+ } else if (methodCache .get ().get (key ) == null ) { // we did not find this method last time!
94
+ return null ;
95
+ } else {
96
+ m = methodCache .get ().get (key ); // method found!
97
+ }
98
+
99
+ if (m != null ){
100
+ return propertyName == null ? m .invoke (obj ) : m .invoke (obj , propertyName );
101
+ }else {
102
+ return null ;
103
+ }
48
104
}
49
105
106
+
50
107
Object valueFrom (Map values ) {
51
- Object obj = values .get (firstId );
52
- for (String id : ids ) {
53
- obj = valueOf (obj , id );
108
+ try {
109
+ Object obj = values .get (firstId );
110
+ for (String id : ids ) {
111
+ obj = valueOf (obj , id );
112
+ }
113
+ return obj ;
114
+ }catch (Exception e ){
115
+ throw new TemplateException (e );
54
116
}
55
- return obj ;
117
+
56
118
}
57
119
}
0 commit comments