1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.monitoring.reporting;
19
20 import java.lang.reflect.Method;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.Stack;
26 import java.util.StringTokenizer;
27
28 import org.apache.commons.monitoring.Monitor.Key;
29
30
31
32
33
34
35
36
37 public class Selector
38 {
39
40
41
42
43 private static final String SEP = "/";
44 private String path;
45
46
47
48
49
50
51 public Selector( String path )
52 {
53 super();
54 this.path = path;
55 }
56
57
58
59
60 public Object select( Object resource )
61 {
62 Stack<String> stack = new Stack<String>();
63 StringTokenizer tokenizer = new StringTokenizer( path, SEP, true );
64 String previous = null;
65 while( tokenizer.hasMoreTokens() )
66 {
67 String next = tokenizer.nextToken();
68 if ( SEP.equals( next ) )
69 {
70 if ( SEP.equals( previous ) )
71 {
72 stack.push( Key.DEFAULT );
73 }
74 }
75 else
76 {
77 stack.push( next );
78 }
79 previous = next;
80 }
81 if ( path.endsWith( SEP ) )
82 {
83
84 stack.push( "" );
85 }
86 Collections.reverse( stack );
87
88 return select( resource, stack );
89 }
90
91 @SuppressWarnings( "unchecked" )
92 protected Object select( Object resource, Stack<String> path )
93 throws IllegalArgumentException
94 {
95 String element = path.pop();
96 Method accessor = getAccessor( resource, element );
97 int i = accessor.getParameterTypes().length;
98 Object[] args = new Object[i];
99 if ( path.size() < i )
100 {
101 throw new IllegalArgumentException( "No enough arguments to call " + accessor );
102 }
103 for ( int j = 0; j < i; j++ )
104 {
105 args[j] = path.pop();
106 }
107 try
108 {
109 resource = accessor.invoke( resource, args );
110 }
111 catch ( Exception e )
112 {
113 throw new IllegalArgumentException( "Failed to invoke " + accessor );
114 }
115
116 if ( resource instanceof Collection && !path.isEmpty() )
117 {
118 Collection input = (Collection) resource;
119 Collection result = new ArrayList( input.size() );
120 for ( Iterator iterator = input.iterator(); iterator.hasNext(); )
121 {
122 Object sub = (Object) iterator.next();
123 Stack<String> branch = new Stack<String>();
124 branch.addAll( path );
125 result.add( select( sub, branch ) );
126 }
127 path.clear();
128 resource = result;
129 }
130
131 if ( !path.isEmpty() )
132 {
133 resource = select( resource, path );
134 }
135 return resource;
136 }
137
138
139
140
141
142
143
144
145
146
147 @SuppressWarnings( "unchecked" )
148 protected Method getAccessor( Object resource, String name )
149 {
150 String accessor = "get";
151 if ( name.length() > 0 )
152 {
153 accessor += Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 );
154 }
155 Method[] methods = resource.getClass().getMethods();
156 Method bestMatch = null;
157 for ( int i = 0; i < methods.length; i++ )
158 {
159 Method method = methods[i];
160 if ( method.getName().equals( accessor ) )
161 {
162 Class[] parameters = method.getParameterTypes();
163 boolean stringsOnly = true;
164 for ( int j = 0; j < parameters.length; j++ )
165 {
166 if ( parameters[j] != String.class )
167 {
168 stringsOnly = false;
169 break;
170 }
171 }
172 if ( stringsOnly )
173 {
174 if ( bestMatch == null || bestMatch.getParameterTypes().length < method.getParameterTypes().length )
175 {
176 bestMatch = method;
177 }
178 }
179 }
180 }
181 if ( bestMatch == null )
182 {
183 throw new IllegalArgumentException( "No accessor for " + name + " on resource " + resource );
184 }
185 return bestMatch;
186 }
187 }