1
2
3
4
5 package xjavadoc;
6
7 import java.util.ArrayList;
8 import java.util.List;
9 import java.util.Collections;
10 import java.util.Iterator;
11 import java.lang.reflect.Modifier;
12
13 /***
14 * Baseclass for XExecutableMember.
15 *
16 * @author Aslak Hellesøy
17 * @created 9. mars 2003
18 */
19 abstract class AbstractExecutableMember extends MemberImpl implements XExecutableMember
20 {
21 /***
22 * Maximum dimension of a parameter. We want to avoid exessive Integer object
23 * creation.
24 */
25 private final static int MAX_ARRAY_SIZE = 6;
26 private final static Integer[] _dimensions = new Integer[MAX_ARRAY_SIZE];
27
28 /***
29 * Initial size of data to hold parameters. Estimate of average number of
30 * params in a method.
31 */
32 private final static int PARAMETER_DATA_SIZE = 2;
33
34 /***
35 * Initial size of ParameterImpl pool. Estimate of max number of params in a
36 * method
37 */
38 private final static int INITIAL_PARAMETER_POOL_SIZE = 20;
39 private static ParameterImpl[] _parameterPool = new ParameterImpl[INITIAL_PARAMETER_POOL_SIZE];
40 private List _thrownExceptions;
41 private List _parameterData;
42 private String _nameWithSignature;
43 private String _signature;
44 private String _stringId;
45
46 static
47 {
48 for( int i = 0; i < MAX_ARRAY_SIZE; i++ )
49 {
50 _dimensions[i] = new Integer( i );
51 }
52 }
53
54 static
55 {
56 for( int i = 0; i < INITIAL_PARAMETER_POOL_SIZE; i++ )
57 {
58 _parameterPool[i] = new ParameterImpl();
59 }
60 }
61
62 protected AbstractExecutableMember( AbstractClass containingClass, XTagFactory tagFactory )
63 {
64 super( containingClass, tagFactory );
65 if( containingClass == null )
66 {
67 throw new IllegalArgumentException( "containingClass can't be null" );
68 }
69 }
70
71 private final static String toString( XParameter parameter, boolean withParam )
72 {
73 if( parameter == null )
74 {
75 throw new IllegalStateException( "parameter can't be null!" );
76 }
77
78 StringBuffer sb = new StringBuffer( parameter.getType().getQualifiedName() );
79
80 Util.appendDimensionAsString( parameter.getDimension(), sb );
81 if( withParam )
82 {
83 sb.append( " " ).append( parameter.getName() );
84 }
85 return sb.toString();
86 }
87
88 /***
89 * Gets the Native attribute of the AbstractExecutableMember object
90 *
91 * @return The Native value
92 */
93 public final boolean isNative()
94 {
95 return ( getModifierSpecifier() & Modifier.NATIVE ) != 0;
96 }
97
98 /***
99 * Gets the Synchronized attribute of the AbstractExecutableMember object
100 *
101 * @return The Synchronized value
102 */
103 public final boolean isSynchronized()
104 {
105 return ( getModifierSpecifier() & Modifier.SYNCHRONIZED ) != 0;
106 }
107
108 /***
109 * Returns the method parameters.
110 *
111 * @return the method parameters
112 */
113 public final List getParameters()
114 {
115 List parameters = null;
116
117 if( _parameterData == null )
118 {
119 parameters = EMPTY_LIST;
120 }
121 else
122 {
123 int requiredSize = _parameterData.size() / 3;
124
125 parameters = new ArrayList( requiredSize );
126 if( _parameterPool.length < requiredSize )
127 {
128
129 ParameterImpl[] newPool = new ParameterImpl[requiredSize];
130
131 System.arraycopy( _parameterPool, 0, newPool, 0, _parameterPool.length );
132 for( int j = _parameterPool.length; j < newPool.length; j++ )
133 {
134 newPool[j] = new ParameterImpl();
135 }
136 _parameterPool = newPool;
137 }
138
139 for( int i = 0; i < requiredSize; i++ )
140 {
141 try
142 {
143 _parameterPool[i].setState( this, i );
144 parameters.add( _parameterPool[i] );
145 }
146 catch( IndexOutOfBoundsException e )
147 {
148 throw new IllegalStateException( "In member " + getName() + ". Tried to set " + i + "th parameter. Size was " + requiredSize );
149 }
150 }
151 }
152 return Collections.unmodifiableList( parameters );
153 }
154
155 /***
156 * Gets the signature
157 *
158 * @param withParam if true, include the parameters in the signature.
159 * Otherwise, only the types will be used.
160 * @return the signature
161 */
162 public final String getSignature( boolean withParam )
163 {
164 if( _signature == null )
165 {
166 _signature = appendSignature( new StringBuffer(), withParam ).toString();
167 }
168 return _signature;
169 }
170
171 /***
172 * Gets the name and signature
173 *
174 * @param withParam if true, include the parameters in the signature.
175 * Otherwise, only the types will be used.
176 * @return the name and signature
177 */
178 public final String getNameWithSignature( boolean withParam )
179 {
180 if( _nameWithSignature == null )
181 {
182 _nameWithSignature = appendSignature( new StringBuffer( getName() ), withParam ).toString();
183 }
184 return _nameWithSignature;
185 }
186
187 public String getParameterTypes()
188 {
189 StringBuffer sb = new StringBuffer();
190
191 for( Iterator i = getParameters().iterator(); i.hasNext(); )
192 {
193
194 ( ( XParameter ) i.next() ).getType();
195 }
196
197 boolean comma = false;
198
199 for( Iterator i = getParameters().iterator(); i.hasNext(); )
200 {
201
202
203
204
205
206 if( comma )
207 {
208 sb.append( ',' );
209 }
210
211 XParameter parameter = ( XParameter ) i.next();
212
213 sb.append( parameter.getType().getType() );
214 comma = true;
215 }
216 return sb.toString();
217 }
218
219 public List getThrownExceptions()
220 {
221 return _thrownExceptions == null ? EMPTY_LIST : Collections.unmodifiableList( getQualifiedExceptions() );
222 }
223
224 public XProgramElement getSuperElement( boolean forMethod )
225 {
226 XClass superclass = getContainingClass().getSuperclass();
227
228 while( superclass != null )
229 {
230 XExecutableMember superExecutableMember;
231
232 if( forMethod )
233 {
234 superExecutableMember = superclass.getMethod( getNameWithSignature( false ) );
235 }
236 else
237 {
238
239 superExecutableMember = superclass.getConstructor( getNameWithSignature( false ) );
240 }
241 if( superExecutableMember != null )
242 {
243 return superExecutableMember;
244 }
245 else
246 {
247 superclass = superclass.getSuperclass();
248 }
249 }
250 return null;
251 }
252
253 public boolean throwsException( String exception_class_name )
254 {
255
256 for( Iterator iterator = getThrownExceptions().iterator(); iterator.hasNext(); )
257 {
258 XClass exception = (XClass) iterator.next();
259
260 if( exception.getQualifiedName().equals( exception_class_name ) )
261 return true;
262 }
263
264 return false;
265 }
266
267 /***
268 * Adds a parameter
269 *
270 * @param type qualified nyme of parameter type
271 * @param name parameter name
272 * @param dimension parameter dimension
273 */
274 public void addParameterData( String type, String name, int dimension )
275 {
276 if( _parameterData == null )
277 {
278 _parameterData = new ArrayList( PARAMETER_DATA_SIZE * 3 );
279 }
280 _parameterData.add( type );
281 _parameterData.add( name );
282 _parameterData.add( _dimensions[dimension] );
283 }
284
285 public void addThrownException( String thrownException )
286 {
287 if( _thrownExceptions == null )
288 {
289 _thrownExceptions = new ArrayList();
290 }
291 _thrownExceptions.add( thrownException );
292 }
293
294 public boolean equals( Object o )
295 {
296 if( !( o.getClass() == getClass() ) )
297 {
298 return false;
299 }
300
301 AbstractExecutableMember other = ( AbstractExecutableMember ) o;
302
303 return stringId().equals( other.stringId() );
304 }
305
306 public int hashCode()
307 {
308 return stringId().hashCode();
309 }
310
311 public String toString()
312 {
313 return stringId();
314 }
315
316 protected abstract String buildStringId();
317
318 final String getParameterType( int index )
319 {
320 return ( String ) _parameterData.get( index * 3 );
321 }
322
323 final String getParameterName( int index )
324 {
325 return ( String ) _parameterData.get( index * 3 + 1 );
326 }
327
328 final int getParameterDimension( int index )
329 {
330 return ( ( Integer ) _parameterData.get( index * 3 + 2 ) ).intValue();
331 }
332
333 private List getQualifiedExceptions()
334 {
335
336 if( _thrownExceptions.get( 0 ) instanceof String )
337 {
338 List qualified_thrown_exceptions = new ArrayList();
339
340 for( Iterator iterator = _thrownExceptions.iterator(); iterator.hasNext(); )
341 {
342 String exception_class_name = ( String ) iterator.next();
343
344 qualified_thrown_exceptions.add( getContainingAbstractClass().qualify( exception_class_name ) );
345 }
346
347 _thrownExceptions = qualified_thrown_exceptions;
348 }
349
350 return _thrownExceptions;
351 }
352
353 /***
354 * Gets the StringId attribute of the MethodImpl object
355 *
356 * @return The StringId value
357 */
358 private final String stringId()
359 {
360 if( _stringId == null )
361 {
362 _stringId = buildStringId();
363 }
364 return _stringId;
365 }
366
367 private final StringBuffer appendSignature( StringBuffer sb, boolean withParam )
368 {
369 sb.append( '(' );
370
371 for( Iterator i = getParameters().iterator(); i.hasNext(); )
372 {
373
374 ( ( XParameter ) i.next() ).getType();
375 }
376
377 boolean comma = false;
378
379 for( Iterator i = getParameters().iterator(); i.hasNext(); )
380 {
381
382
383
384
385
386 if( comma )
387 {
388 sb.append( ',' );
389 }
390 sb.append( toString( ( XParameter ) i.next(), withParam ) );
391 comma = true;
392 }
393 return sb.append( ')' );
394 }
395 }