1 /*
2 * Copyright (C) The Spice Group. All rights reserved.
3 *
4 * This software is published under the terms of the Spice
5 * Software License version 1.1, a copy of which has been included
6 * with this distribution in the LICENSE.txt file.
7 */
8 package org.realityforge.metaclass.tools.qdox;
9
10 import com.thoughtworks.qdox.model.DocletTag;
11 import com.thoughtworks.qdox.model.JavaClass;
12 import com.thoughtworks.qdox.model.JavaField;
13 import com.thoughtworks.qdox.model.JavaMethod;
14 import com.thoughtworks.qdox.model.JavaParameter;
15 import com.thoughtworks.qdox.model.Type;
16 import java.util.ArrayList;
17 import java.util.Properties;
18 import org.realityforge.metaclass.model.Attribute;
19 import org.realityforge.metaclass.model.ClassDescriptor;
20 import org.realityforge.metaclass.model.FieldDescriptor;
21 import org.realityforge.metaclass.model.MethodDescriptor;
22 import org.realityforge.metaclass.model.ParameterDescriptor;
23
24 /***
25 * This class is responsible for parsing a JavaClass object
26 * and building a ClassDescriptor to correspond to the JavaClass
27 * object.
28 *
29 * @version $Revision: 1.20 $ $Date: 2003/10/28 13:40:52 $
30 */
31 public class QDoxDescriptorParser
32 {
33 /***
34 * Constant indicating parse state is
35 * before the start of key.
36 */
37 private static final int PARSE_KEY_START = 0;
38
39 /***
40 * Constant indicating parse state is
41 * parsing the key.
42 */
43 private static final int PARSE_KEY = 1;
44
45 /***
46 * Constant indicating parse state is
47 * before the start of value and expecting ".
48 */
49 private static final int PARSE_VALUE_START = 2;
50
51 /***
52 * Constant indicating parse state is
53 * parsing value string.
54 */
55 private static final int PARSE_VALUE = 3;
56
57 /***
58 * Constant indicating parse state is
59 * after value closed.
60 */
61 private static final int PARSE_END = 4;
62
63 /***
64 * Build a ClassDescriptor for a JavaClass.
65 *
66 * @param javaClass the JavaClass
67 * @return the ClassDescriptor
68 */
69 public ClassDescriptor buildClassDescriptor( final JavaClass javaClass )
70 {
71 return buildClassDescriptor( javaClass, new DefaultQDoxAttributeInterceptor() );
72 }
73
74 /***
75 * Build a ClassDescriptor for a JavaClass.
76 *
77 * @param javaClass the JavaClass
78 * @param interceptors the AttributeInterceptors
79 * @return the ClassDescriptor
80 */
81 public ClassDescriptor buildClassDescriptor( final JavaClass javaClass,
82 final QDoxAttributeInterceptor[] interceptors )
83 {
84 return buildClassDescriptor( javaClass, new MulticastInterceptor( interceptors ) );
85 }
86
87 /***
88 * Build a ClassDescriptor for a JavaClass.
89 *
90 * @param javaClass the JavaClass
91 * @param interceptor the AttributeInterceptor
92 * @return the ClassDescriptor
93 */
94 public ClassDescriptor buildClassDescriptor( final JavaClass javaClass,
95 final QDoxAttributeInterceptor interceptor )
96 {
97 final String classname = javaClass.getFullyQualifiedName();
98 final Attribute[] originalAttributes = buildAttributes( javaClass, interceptor );
99 final Attribute[] attributes =
100 interceptor.processClassAttributes( javaClass, originalAttributes );
101
102 final FieldDescriptor[] fields =
103 buildFields( javaClass.getFields(), interceptor );
104 final MethodDescriptor[] methods =
105 buildMethods( javaClass.getMethods(), interceptor );
106
107 return new ClassDescriptor( classname,
108 attributes,
109 attributes,
110 fields,
111 methods );
112 }
113
114 /***
115 * Build a set of MethodDescriptor instances for a JavaClass.
116 *
117 * @param methods the methods
118 * @param interceptor the AttributeInterceptor
119 * @return the MethodDescriptors
120 */
121 MethodDescriptor[] buildMethods( final JavaMethod[] methods,
122 final QDoxAttributeInterceptor interceptor )
123 {
124 final MethodDescriptor[] methodDescriptors = new MethodDescriptor[ methods.length ];
125 for( int i = 0; i < methods.length; i++ )
126 {
127 methodDescriptors[ i ] = buildMethod( methods[ i ], interceptor );
128 }
129 return methodDescriptors;
130 }
131
132 /***
133 * Build a MethodDescriptor for a JavaMethod.
134 *
135 * @param method the JavaMethod
136 * @param interceptor the AttributeInterceptor
137 * @return the MethodDescriptor
138 */
139 MethodDescriptor buildMethod( final JavaMethod method,
140 final QDoxAttributeInterceptor interceptor )
141 {
142 final String name = method.getName();
143 final Type returns = method.getReturns();
144 final String type;
145 if( null != returns )
146 {
147 type = returns.getValue();
148 }
149 else
150 {
151 type = "";
152 }
153
154 final Attribute[] originalAttributes = buildAttributes( method, interceptor );
155 final Attribute[] attributes =
156 interceptor.processMethodAttributes( method, originalAttributes );
157 final ParameterDescriptor[] parameters =
158 buildParameters( method.getParameters() );
159
160 return new MethodDescriptor( name,
161 type,
162 parameters,
163 attributes,
164 attributes );
165 }
166
167 /***
168 * Build a set of ParameterDescriptor for JavaParameters.
169 *
170 * @param parameters the JavaParameters
171 * @return the ParameterDescriptors
172 */
173 ParameterDescriptor[] buildParameters( final JavaParameter[] parameters )
174 {
175 final ParameterDescriptor[] descriptors =
176 new ParameterDescriptor[ parameters.length ];
177 for( int i = 0; i < parameters.length; i++ )
178 {
179 descriptors[ i ] = buildParameter( parameters[ i ] );
180 }
181 return descriptors;
182 }
183
184 /***
185 * Build a ParameterDescriptor for a JavaParameter.
186 *
187 * @param parameter the JavaParameter
188 * @return the ParameterDescriptor
189 */
190 ParameterDescriptor buildParameter( final JavaParameter parameter )
191 {
192 final String name = parameter.getName();
193 final String value = parameter.getType().getValue();
194 return new ParameterDescriptor( name, value );
195 }
196
197 /***
198 * Build a set of FieldDescriptor instances for a JavaClass.
199 *
200 * @param fields the fields
201 * @param interceptor the AttributeInterceptor
202 * @return the FieldDescriptors
203 */
204 FieldDescriptor[] buildFields( final JavaField[] fields,
205 final QDoxAttributeInterceptor interceptor )
206 {
207 final FieldDescriptor[] fieldDescriptors = new FieldDescriptor[ fields.length ];
208 for( int i = 0; i < fields.length; i++ )
209 {
210 fieldDescriptors[ i ] = buildField( fields[ i ], interceptor );
211 }
212 return fieldDescriptors;
213 }
214
215 /***
216 * Build a set of FieldDescriptor instances for a JavaField.
217 *
218 * @param field the JavaField
219 * @param interceptor the AttributeInterceptor
220 * @return the FieldDescriptor
221 */
222 FieldDescriptor buildField( final JavaField field,
223 final QDoxAttributeInterceptor interceptor )
224 {
225 final String name = field.getName();
226 final String type = field.getType().getValue();
227 final Attribute[] originalAttributes = buildAttributes( field, interceptor );
228 final Attribute[] attributes =
229 interceptor.processFieldAttributes( field, originalAttributes );
230 return new FieldDescriptor( name,
231 type,
232 attributes,
233 attributes );
234 }
235
236 /***
237 * Build a set of Attribute instances for a JavaClass.
238 * Use Interceptor to process tags during construction.
239 *
240 * @param javaClass the JavaClass
241 * @param interceptor the AttributeInterceptor
242 * @return the Attributes
243 */
244 private Attribute[] buildAttributes( final JavaClass javaClass,
245 final QDoxAttributeInterceptor interceptor )
246 {
247 final ArrayList attributes = new ArrayList();
248 final DocletTag[] tags = javaClass.getTags();
249 for( int i = 0; i < tags.length; i++ )
250 {
251 final Attribute originalAttribute = buildAttribute( tags[ i ] );
252 final Attribute attribute =
253 interceptor.processClassAttribute( javaClass, originalAttribute );
254 if( null != attribute )
255 {
256 attributes.add( attribute );
257 }
258 }
259 return (Attribute[])attributes.toArray( new Attribute[ attributes.size() ] );
260 }
261
262 /***
263 * Build a set of Attribute instances for a JavaMethod.
264 * Use Interceptor to process tags during construction.
265 *
266 * @param method the JavaMethod
267 * @param interceptor the AttributeInterceptor
268 * @return the Attributes
269 */
270 private Attribute[] buildAttributes( final JavaMethod method,
271 final QDoxAttributeInterceptor interceptor )
272 {
273 final ArrayList attributes = new ArrayList();
274 final DocletTag[] tags = method.getTags();
275 for( int i = 0; i < tags.length; i++ )
276 {
277 final Attribute originalAttribute = buildAttribute( tags[ i ] );
278 final Attribute attribute =
279 interceptor.processMethodAttribute( method, originalAttribute );
280 if( null != attribute )
281 {
282 attributes.add( attribute );
283 }
284 }
285 return (Attribute[])attributes.toArray( new Attribute[ attributes.size() ] );
286 }
287
288 /***
289 * Build a set of Attribute instances for a JavaField.
290 * Use Interceptor to process tags during construction.
291 *
292 * @param field the JavaField
293 * @param interceptor the AttributeInterceptor
294 * @return the Attributes
295 */
296 private Attribute[] buildAttributes( final JavaField field,
297 final QDoxAttributeInterceptor interceptor )
298 {
299 final ArrayList attributes = new ArrayList();
300 final DocletTag[] tags = field.getTags();
301 for( int i = 0; i < tags.length; i++ )
302 {
303 final Attribute originalAttribute = buildAttribute( tags[ i ] );
304 final Attribute attribute =
305 interceptor.processFieldAttribute( field, originalAttribute );
306 if( null != attribute )
307 {
308 attributes.add( attribute );
309 }
310 }
311 return (Attribute[])attributes.toArray( new Attribute[ attributes.size() ] );
312 }
313
314 /***
315 * Build an Attribute object from a DocletTag.
316 *
317 * @param tag the DocletTag instance.
318 * @return the Attribute
319 */
320 Attribute buildAttribute( final DocletTag tag )
321 {
322 final String name = tag.getName();
323 final String value = tag.getValue();
324 if( null == value || "".equals( value.trim() ) )
325 {
326 return new Attribute( name );
327 }
328
329 final Properties parameters = parseValueIntoParameters( value );
330 if( null == parameters )
331 {
332 return new Attribute( name, value );
333 }
334 else
335 {
336 return new Attribute( name, parameters );
337 }
338 }
339
340 /***
341 * Parse the value string into a set of parameters.
342 * The parameters must match the pattern
343 *
344 * <pre>
345 * ^[ \t\r\n]*([a-zA-Z\_][a-zA-Z0-9\_]*=\"[^\"]*\"[ \t\r\n]+)+
346 * </pre>
347 *
348 * <p>If the value does not match this pattern then null is returned
349 * other wise the key=value pairs are parsed out and placed in
350 * a properties object.</p>
351 *
352 * @param input the input value
353 * @return the parameters if matches patterns, else null
354 */
355 Properties parseValueIntoParameters( final String input )
356 {
357 final Properties parameters = new Properties();
358
359 final StringBuffer key = new StringBuffer();
360 final StringBuffer value = new StringBuffer();
361
362 int state = PARSE_KEY_START;
363 final int length = input.length();
364 for( int i = 0; i < length; i++ )
365 {
366 final char ch = input.charAt( i );
367 switch( state )
368 {
369 case PARSE_KEY_START:
370 if( Character.isWhitespace( ch ) )
371 {
372 continue;
373 }
374 else if( Character.isJavaIdentifierStart( ch ) )
375 {
376 key.append( ch );
377 state = PARSE_KEY;
378 }
379 else
380 {
381 return null;
382 }
383 break;
384
385 case PARSE_KEY:
386 if( '=' == ch )
387 {
388 state = PARSE_VALUE_START;
389 }
390 else if( Character.isJavaIdentifierPart( ch ) )
391 {
392 key.append( ch );
393 }
394 else
395 {
396 return null;
397 }
398 break;
399
400 case PARSE_VALUE_START:
401 if( '\"' != ch )
402 {
403 return null;
404 }
405 else
406 {
407 state = PARSE_VALUE;
408 }
409 break;
410
411 case PARSE_VALUE:
412 if( '\"' == ch )
413 {
414 state = PARSE_END;
415 parameters.setProperty( key.toString(), value.toString() );
416 key.setLength( 0 );
417 value.setLength( 0 );
418 }
419 else
420 {
421 value.append( ch );
422 }
423 break;
424
425 case PARSE_END:
426 default:
427 if( Character.isWhitespace( ch ) )
428 {
429 state = PARSE_KEY_START;
430 }
431 else
432 {
433 return null;
434 }
435 break;
436 }
437 }
438
439 if( PARSE_KEY_START != state &&
440 PARSE_END != state )
441 {
442 return null;
443 }
444
445 return parameters;
446 }
447 }
This page was automatically generated by Maven