Erik
I did not read method comments :(
What I have corrected is that if parameters is not specified then he
search for a method with no parameters at all.
Here attached the correction (hopefully)
I will put that in CVS when possible.
Vincent
--- Erik Hatcher <[EMAIL PROTECTED]> wrote:
> Vincent,
>
> I thanked you (offline) before trying it, but this fix is not working
> for
> me. It is still having the same behavior (not picking up a method if
> parameters is not specified).
>
> I've verified that I'm running the latest from CVS.
>
> Erik
>
>
> ----- Original Message -----
> From: "Vincent Harcq" <[EMAIL PROTECTED]>
> To: "'Erik Hatcher'" <[EMAIL PROTECTED]>;
> <[EMAIL PROTECTED]>
> Sent: Tuesday, February 26, 2002 1:05 AM
> Subject: RE: [Xdoclet-devel] Re: [Xdoclet-user] XDtMethod:ifHasMethod
> ????
>
>
> Hi,
> There was a bug.
> This has been fixed in CVS.
> Thanks for reporting.
> Vincent.
>
> > -----Original Message-----
> > From: [EMAIL PROTECTED]
> > [mailto:[EMAIL PROTECTED]] On Behalf
> > Of Erik Hatcher
> > Sent: mardi 26 f�vrier 2002 0:33
> > To: [EMAIL PROTECTED]
> > Subject: [Xdoclet-devel] Re: [Xdoclet-user] XDtMethod:ifHasMethod
> ????
> >
> >
> > Now posting this over to -devel. It seems that ifHasMethod
> > is broken. Or is it just me?
> >
> >
> >
> > ----- Original Message -----
> > From: "Erik Hatcher" <[EMAIL PROTECTED]>
> >
> > > <XDtMethod:ifHasMethod name="setValue">
> > > without parameters
> > > </XDtMethod:ifHasMethod>
> > >
> > > <XDtMethod:ifHasMethod name="setValue"
> > parameters="java.lang.String">
> > > with parameters
> > > </XDtMethod:ifHasMethod>
> > >
> > > All I get generated is "with parameters". That is not what the
> > > documentation says about ifHasMethod:
> > >
> > > "Evaluate the body if current class has a method with the
> specified
> > > name+parameters. If parameters not specified then any
> > method with the
> > given
> > > name and any set of parameters is considered equal to the
> > given method
> > name
> > > and so the test result is positive and the body is evaluated.
> This
> > > method does not change the current method to the one specified."
> > >
> > > Clearly I have a setValue method - so why doesn't the first
> > > ifHasMethod
> > pick
> > > it up? Shouldn't it?
> > >
> > > I tried replacing the first 'ifHasMethod' with
> > 'setCurrentMethod' and
> > > it still did not get picked up.
> >
> >
> >
> > _______________________________________________
> > Xdoclet-devel mailing list
> > [EMAIL PROTECTED]
> > https://lists.sourceforge.net/lists/listinfo/xdoclet-devel
> >
> >
>
>
>
>
>
> _______________________________________________
> Xdoclet-devel mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/xdoclet-devel
>
>
>
__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com
package xdoclet.tags;
import com.sun.javadoc.*;
import xdoclet.XDocletException;
import xdoclet.ejb.DataObjectSubTask;
import xdoclet.template.PrettyPrintWriter;
import xdoclet.util.DocletUtil;
import xdoclet.util.TypeConversionUtil;
import xdoclet.util.Log;
import xdoclet.util.Translator;
import java.beans.Introspector;
import java.util.*;
import org.apache.log4j.Category;
/**
* @author Ara Abrahamian ([EMAIL PROTECTED])
* @created Oct 15, 2001
* @version $Revision: 1.23 $
*/
public class MethodTagsHandler extends AbstractProgramElementTagsHandler
{
public static String getMethodTypeFor( MethodDoc method ) throws
XDocletException
{
return method.returnType().qualifiedTypeName() +
method.returnType().dimension();
}
/**
* Merge with modified SubTask.methodNameWithoutPrefix
*
* @param cur_method Description of Parameter
* @return Description of the Returned Value
*/
public static String getMethodNameWithoutPrefixFor( MethodDoc cur_method )
{
String str = cur_method.name();
if( str.startsWith( "get" ) || str.startsWith( "set" ) )
return str.substring( 3 );
else if( str.startsWith( "is" ) )
return str.substring( 2 );
else
return str;
}
public static String getPropertyNameFor( MethodDoc method )
{
String name = getMethodNameWithoutPrefixFor( method );
int len = name.length();
if( len == 0 )
return name;
if( len == 1 )
return name.toLowerCase();
//Turn first letter to lower case (only if it's currently uppercase)
char c = name.charAt( 0 );
if( c >= 'A' && c <= 'Z' )
return ( ( char ) ( c + ( 'a' - 'A' ) ) ) + name.substring( 1
);
return name;
}
/**
* Returns true if the str string starts with a getter prefix ("get" or "is").
*
* @param str Description of Parameter
* @return The Getter value
*/
public static boolean isGetter( String str )
{
return str.startsWith( "get" ) || str.startsWith( "is" );
}
/**
* Returns true if a method with the specified methodName+parameters is found
* in the class clazz. The parameters array can be empty, if so any method with
* any set of parameters is considered equal to the method we're searching for.
* if not empty all parameters of the method must be equal to the ones
* specified in parameters array to have "method equality".
*
* @param clazz Description of Parameter
* @param methodName Description of Parameter
* @param parameters Description of Parameter
* @return Description of the Returned Value
*/
protected static boolean hasMethod( ClassDoc clazz, String methodName,
String[] parameters )
{
Category cat = Log.getCategory( MethodTagsHandler.class, "hasMethod" );
while( clazz != null )
{
MethodDoc[] methods = clazz.methods();
methodLoop :
for( int i = 0; i < methods.length; i++ )
{
if( methods[i].name().equals( methodName ) )
{
// All parameters must be equal to have
"method equality"
Parameter[] params = methods[i].parameters();
cat.debug( "params.length=" + params.length );
for( int j = 0; j < params.length; j++ )
{
cat.debug( "params[j].typeName()=" +
params[j].typeName() );
cat.debug( "parameters[j]=" +
parameters[j] );
if( parameters == null ||
!params[j].typeName().equals( parameters[j] ) )
continue methodLoop;
}
// The class has the given method
return true;
}
}
// Check super class info
clazz = clazz.superclass();
}
return false;
}
/**
* Returns 'get' or 'is' getter prefix part of the current method. Returns
* empty string if the method doesn't start with either of the two getter
* prefixes.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String getterPrefix() throws XDocletException
{
String prefix = "";
if( getCurrentMethod().name().startsWith( "get" ) )
prefix = "get";
else if( getCurrentMethod().name().startsWith( "is" ) )
prefix = "is";
else if( getCurrentMethod().name().startsWith( "set" ) )
{
// For boolean here we don't know if it is get or is, lets
find it
String[] params = {getCurrentMethod().returnType().typeName()};
if( hasMethod( getCurrentClass(), "is" +
methodNameWithoutPrefix(), params, false ) )
prefix = "is";
else
return prefix = "get";
}
return prefix;
}
/**
* Returns the getter method name for the current method by prefixing the
* method name with the proper getter prefix.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @see #methodNameWithoutPrefix()
* @see #setterMethod()
* @see #getterPrefix()
* @doc:tag type="content"
*/
public String getterMethod() throws XDocletException
{
return getterPrefix() + methodNameWithoutPrefix();
}
/**
* Returns the setter method name for the current method by prefixing the
* method name with a 'set' and removing the getter method's 'get' or 'is'
* prefixes, if any.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @see #methodNameWithoutPrefix()
* @see #getterMethod()
* @doc:tag type="content"
*/
public String setterMethod() throws XDocletException
{
return "set" + methodNameWithoutPrefix();
}
/**
* Evaluate the body if current class has a method with the specified
* name+parameters. If parameters not specified then any method with the given
* name and any set of parameters is considered equal to the given method name
* and so the test result is positive and the body is evaluated. This method
* change the current method to the one specified.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @see
#ifHasMethod(java.lang.String,java.util.Properties)
* @doc:tag type="block"
* @doc:param name="name" optional="false" description="The
* name of the method we're searching for its existence in current class."
* @doc:param name="parameters" optional="true"
* description="We're searching for a method that has the exact set of
* parameters specified in parameters param."
* @doc:param name="delimiter" optional="true"
* description="The parameters param is delimited by the string specified
* in delimiter parameter."
*/
public void setCurrentMethod( String template, Properties attributes ) throws
XDocletException
{
String methodName = attributes.getProperty( "name" );
String parametersStr = attributes.getProperty( "parameters" );
String delimiter = attributes.getProperty( "delimiter" );
String[] parameters = null;
if( parametersStr != null )
{
if( delimiter == null )
delimiter = PARAMETER_DELIMITER;
parameters = DocletUtil.tokenizeDelimitedToArray(
parametersStr, delimiter );
}
MethodDoc oldMethod = getCurrentMethod();
if( hasMethod( getCurrentClass(), methodName, parameters, true ) ==
true )
{
generate( template );
}
setCurrentMethod( oldMethod );
}
/**
* The comment for the current method.
*
* @param attributes The attributes of the template tag
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @see
ClassTagsHandler#classComment(java.util.Properties)
* @doc:tag type="content"
* @doc:param name="no-comment-signs" optional="true"
* values="true,false" description="If true then don't decorate the
* comment with comment signs."
*/
public String methodComment( Properties attributes ) throws XDocletException
{
String no_comment_signs = attributes.getProperty( "no-comment-signs" );
if( no_comment_signs != null && no_comment_signs.equalsIgnoreCase(
"true" ) )
return getCurrentMethod().commentText();
char[] spaces = getIndentChars( attributes );
Tag[] method_tags = getCurrentMethod().tags();
if( method_tags.length > 0 )
{
StringBuffer result = new StringBuffer();
//add user comments
StringTokenizer st = new StringTokenizer(
getCurrentMethod().commentText().trim(), "\n", false );
if( st.countTokens() > 0 )
{
result.append( spaces ).append( "/**" ).append(
PrettyPrintWriter.LINE_SEPARATOR );
while( st.hasMoreTokens() )
{
result.append( spaces ).append( " * "
).append( st.nextToken().trim() ).append( PrettyPrintWriter.LINE_SEPARATOR );
}
for( int i = 0; i < method_tags.length; i++ )
{
//all of our xdoclet-specific tags have a ":"
if( method_tags[i].name().lastIndexOf( ':' )
== -1 )
{
result.append( spaces ).append( " * " )
.append( method_tags[i].name()
).append( ' ' )
.append( method_tags[i].text()
);
//for all lines but not the last line
if( i < method_tags.length - 1 )
result.append(
PrettyPrintWriter.LINE_SEPARATOR );
}
}
result.append( spaces ).append( " */" );
}
return result.toString();
}
else
return "";
}
/**
* Iterates over all exceptions thrown by the current method and returns a
* string containing definition of all those exceptions.
*
* @param attributes The attributes of the template tag
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="method" optional="true" description="The
* method name of which exceptions list is extracted. If not specified
* then current method is used."
* @doc:param name="skip" optional="true" description="A
* comma-separated list of exceptions that should be skipped and not put
* into the list."
* @doc:param name="append" optional="true" description="A
* comma-separated list of exceptions that should be always appended
* regardless if current method has that method defined or not."
*/
public String exceptionList( Properties attributes ) throws XDocletException
{
String skip_exceptions = attributes.getProperty( "skip" );
String append_exceptions = attributes.getProperty( "append" );
String method_name = attributes.getProperty( "method" );
ClassDoc[] exceptions = null;
if( getCurrentMethod() == null && method_name == null )
return "";
if( method_name == null )
exceptions = getCurrentMethod().thrownExceptions();
else
{
MethodDoc method_doc = getMethodDocForMethodName( method_name,
true );
//no method with the specified name found in class
if( method_doc == null )
return "";
exceptions = method_doc.thrownExceptions();
}
StringBuffer st = new StringBuffer();
String type = null;
for( int i = 0; i < exceptions.length; i++ )
{
type = exceptions[i].toString();
if( isInSkipExceptionsList( skip_exceptions, type ) == false &&
isInAppendExceptionsList( append_exceptions, type ) ==
false )
{
appendException( st, type );
}
}
//append all exceptions specfied to be always appended by default
if( append_exceptions != null )
appendException( st, append_exceptions );
return st.toString();
}
/**
* Evaluate the body block if current method is abstract.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @see
#ifIsNotAbstract(java.lang.String,java.util.Properties)
* @doc:tag type="block"
* @doc:param name="method" optional="true" description="The
* method name of which exceptions list is extracted. If not specified
* then current method is used."
*/
public void ifIsAbstract( String template, Properties attributes ) throws
XDocletException
{
String method_name = attributes.getProperty( "method" );
if( method_name == null )
{
if( getCurrentMethod().isAbstract() )
generate( template );
}
else
{
MethodDoc method_doc = getMethodDocForMethodName( method_name,
false );
//no method with the specified name found in class
if( method_doc == null )
throw new XDocletException( Translator.getString(
"method_not_found", new String[]{method_name} ) );
if( method_doc.isAbstract() )
generate( template );
}
}
/**
* Evaluates the body block if current method is not abstract.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @see
#ifIsAbstract(java.lang.String,java.util.Properties)
* @doc:tag type="block"
* @doc:param name="method" optional="true" description="The
* method name of which exceptions list is extracted. If not specified
* then current method is used."
*/
public void ifIsNotAbstract( String template, Properties attributes ) throws
XDocletException
{
String method_name = attributes.getProperty( "method" );
if( method_name == null )
{
if( !getCurrentMethod().isAbstract() )
generate( template );
}
else
{
MethodDoc method_doc = getMethodDocForMethodName( method_name,
false );
//no method with the specified name found in class
if( method_doc == null )
throw new XDocletException( Translator.getString(
"method_not_found", new String[]{method_name} ) );
if( !method_doc.isAbstract() )
generate( template );
}
}
/**
* Loops through all methods for all classes after first sorting all the
* methods.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="type" optional="true" description="For
* all classes by the type."
* @doc:param name="extent" optional="true"
* values="concrete-type,superclass,hierarchy" description="Specifies the
* extent of the type search. If concrete-type then only check the
* concrete type, if superclass then check also superclass, if hierarchy
* then search the whole hierarchy and find if the class is of the
* specified type. Default is hierarchy."
*/
public void forAllClassMethods( String template, Properties attributes )
throws XDocletException
{
String type_name = attributes.getProperty( "type" );
int extent = TypeTagsHandler.extractExtentType(
attributes.getProperty( "extent" ) );
ClassDoc[] classes = getAllClasses();
SortedSet methods = new TreeSet();
for( int i = 0; i < classes.length; i++ )
{
if( type_name == null || TypeTagsHandler.isOfType( classes[i],
type_name, extent ) )
{
MethodDoc[] classMethods = classes[i].methods();
for( int j = 0; j < classMethods.length; j++ )
methods.add( classMethods[j] );
}
}
Iterator methodsIterator = methods.iterator();
while( methodsIterator.hasNext() )
{
MethodDoc current = ( MethodDoc ) methodsIterator.next();
setCurrentClass( current.containingClass() );
setCurrentMethod( current );
generate( template );
}
}
/**
* Iterates over all methods of current class and evaluates the body of the tag
* for each method.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="superclasses" optional="true"
* values="true,false" description="If true then traverse superclasses
* also, otherwise look up the tag in current concrete class only."
* @doc:param name="sort" optional="true" values="true,false"
* description="If true then sort the methods list."
*/
public void forAllMethods( String template, Properties attributes ) throws
XDocletException
{
boolean superclasses = TypeConversionUtil.stringToBoolean(
attributes.getProperty( "superclasses" ), true );
boolean sort = TypeConversionUtil.stringToBoolean(
attributes.getProperty( "sort" ), true );
ClassDoc cur_class = getCurrentClass();
Map already = new HashMap();
do
{
MethodDoc[] methods = cur_class.methods();
if( sort == true )
{
List the_list = Arrays.asList( methods );
//sort methods
Collections.sort( the_list,
new Comparator()
{
public int compare( Object o1, Object
o2 )
{
MethodDoc m1 = ( MethodDoc )
o1;
MethodDoc m2 = ( MethodDoc )
o2;
return m1.name().compareTo(
m2.name() );
}
public boolean equals( Object obj )
{
//dumb
return obj == this;
}
} );
methods = ( MethodDoc[] ) the_list.toArray( methods );
}
for( int j = 0; j < methods.length; j++ )
{
if( superclasses == false || ( superclasses == true &&
methods[j].containingClass() == cur_class ) )
{
if( already.containsKey( methods[j] ) == false
)
{
setCurrentMethod( methods[j] );
already.put( methods[j], methods[j] );
generate( template );
}
}
}
if( superclasses == true )
cur_class = cur_class.superclass();
else
break;
}while ( cur_class != null );
}
/**
* Evaluates the body if current method doesn't have at least one tag with the
* specified name.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="paramName" description="The parameter
* name. If not specified, then the raw content of the tag is returned."
* @doc:param name="paramNum" description="The zero-based
* parameter number. It's used if the user used the space-separated format
* for specifying parameters."
* @doc:param name="error" description="Show this error
* message if no tag found."
*/
public void ifDoesntHaveMethodTag( String template, Properties attributes )
throws XDocletException
{
if( !ifHasTag_Impl( template, attributes, FOR_METHOD ) )
generate( template );
else
{
String error = attributes.getProperty( "error" );
if( error != null )
getEngine().print( error );
}
}
/**
* Evaluates the body if current method has at least one tag with the specified
* name.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="paramName" description="The parameter
* name. If not specified, then the raw content of the tag is returned."
* @doc:param name="paramNum" description="The zero-based
* parameter number. It's used if the user used the space-separated format
* for specifying parameters."
* @doc:param name="error" description="Show this error
* message if no tag found."
*/
public void ifHasMethodTag( String template, Properties attributes ) throws
XDocletException
{
if( ifHasTag_Impl( template, attributes, FOR_METHOD ) )
generate( template );
else
{
String error = attributes.getProperty( "error" );
if( error != null )
getEngine().print( error );
}
}
/**
* Evaluate the current block, and then restore the current method before
* continuing.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
*/
public void executeAndRestoreMethod( String template, Properties attributes )
throws XDocletException
{
MethodDoc method = getCurrentMethod();
generate( template );
setCurrentMethod( method );
}
/**
* Evaluates the body if value for the method tag equals the specified value.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="paramName" description="The parameter
* name. If not specified, then the raw content of the tag is returned."
* @doc:param name="paramNum" description="The zero-based
* parameter number. It's used if the user used the space-separated format
* for specifying parameters."
*/
public void ifMethodTagValueEquals( String template, Properties attributes )
throws XDocletException
{
if( ifTagValueEquals_Impl( template, attributes, FOR_METHOD ) )
generate( template );
}
/**
* Evaluates the body if value for the method tag not equals the specified
* value.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="paramName" description="The parameter
* name. If not specified, then the raw content of the tag is returned."
* @doc:param name="paramNum" description="The zero-based
* parameter number. It's used if the user used the space-separated format
* for specifying parameters."
*/
public void ifMethodTagValueNotEquals( String template, Properties attributes
) throws XDocletException
{
if( !ifTagValueEquals_Impl( template, attributes, FOR_METHOD ) )
generate( template );
}
/**
* Iterates over all method tags with the specified tagName for the current
* method probably inside of a forAllMethodTags body.
*
* @param attributes The attributes of the template tag
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="paramName" description="The parameter
* name. If not specified, then the raw content of the tag is returned."
* @doc:param name="paramNum" description="The zero-based
* parameter number. It's used if the user used the space-separated format
* for specifying parameters."
* @doc:param name="values" description="The valid values for
* the parameter, comma separated. An error message is printed if the
* parameter value is not one of the values."
* @doc:param name="default" description="The default value
* is returned if parameter not specified by user for the tag."
*/
public String methodTagValue( Properties attributes ) throws XDocletException
{
return getTagValue( attributes, FOR_METHOD );
}
/**
* Iterates over all tags of current method and evaluates the body of the tag
* for each method.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
*/
public void forAllMethodTags( String template, Properties attributes ) throws
XDocletException
{
if( getCurrentMethod() == null )
throw new XDocletException( Translator.getString(
"only_call_method_not_null", new String[]{"forAllMethodTags"} ) );
Tag[] tags = getCurrentMethod().tags( attributes.getProperty(
"tagName" ) );
for( int i = 0; i < tags.length; i++ )
{
setCurrentTag( tags[i] );
String m = getTagValue( attributes, FOR_METHOD );
if( matchPattern == null )
generate( template );
else if( matchPattern != null && ( matchPattern.equals( m ) ||
m.equals( "*" ) ) )
generate( template );
}
setCurrentTag( null );
}
/**
* Iterates over all tokens in current method tag with the name tagName and
* evaluates the body for every token.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @doc:tag type="block"
* @doc:param name="tagName" optional="false"
* description="The tag name."
* @doc:param name="delimiter" description="delimiter for the
* StringTokenizer. consult javadoc for java.util.StringTokenizer default
* is ','"
* @doc:param name="skip" description="how many tokens to
* skip on start"
*/
public void forAllMethodTagTokens( String template, Properties attributes )
throws XDocletException
{
Category cat = Log.getCategory( MethodTagsHandler.class,
"forAllMethodTagTokens" );
// get method tag value to iterate over
String tagValue = getTagValue( attributes, FOR_METHOD );
String delimiter = attributes.getProperty( "delimiter" );
String s = attributes.getProperty( "skip" );
int skip;
try
{
skip = Integer.valueOf( attributes.getProperty( "skip" )
).intValue();
}
catch( Throwable t )
{
skip = 0;
}
if( delimiter == null )
{
if( cat.isDebugEnabled() )
cat.debug( "got null delimiter -
forAllMethodTagTokens" );
delimiter = PARAMETER_DELIMITER;
}
tagTokenizer = new StringTokenizer( tagValue, delimiter, false );
currentToken = "";
matchPattern = null;
for( int i = 0; tagTokenizer.hasMoreTokens() && i < skip; i++ )
tagTokenizer.nextToken();
while( tagTokenizer.hasMoreTokens() )
{
currentToken = tagTokenizer.nextToken();
if( cat.isDebugEnabled() )
cat.debug( "generate current token: " + currentToken );
generate( template );
}
currentToken = null;
tagTokenizer = null;
matchPattern = null;
}
/**
* Return standard javadoc of current method.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String firstSentenceDescriptionOfCurrentMethod() throws XDocletException
{
return getCurrentMethod().firstSentenceTags().length > 0 ?
getCurrentMethod().firstSentenceTags()[0].text().trim() : "";
}
/**
* Returns the return type of the current method.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String methodType() throws XDocletException
{
return getMethodTypeFor( getCurrentMethod() );
}
/**
* Returns the name of the current method.
*
* @param attributes The attributes of the template tag
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String methodName( Properties attributes ) throws XDocletException
{
if( attributes != null )
{
String value = ( String ) attributes.get( "value" );
if( value != null )
{
String m = getCurrentMethod().name().substring(
Integer.parseInt( value ) );
// replace first character to lowercase
char firstU = m.charAt( 0 );
char firstL = Character.toLowerCase( firstU );
return firstL + m.substring( 1 );
}
}
return getCurrentMethod() != null ? getCurrentMethod().name() : "";
}
/**
* Returns the name of the current method without the first three characters.
* Used for cases where the method name without the get/set prefix is needed.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String methodNameWithoutPrefix() throws XDocletException
{
return getMethodNameWithoutPrefixFor( getCurrentMethod() );
}
/**
* Returns the current method name. Used inside block elements.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
*/
public String currentMethodName() throws XDocletException
{
return getCurrentMethod().name();
}
/**
* Returns the property name extracted from the current method name. Remove any
* getter/setter prefix from method name and decapitalize it.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc:tag type="content"
*/
public String propertyName() throws XDocletException
{
return getPropertyNameFor( getCurrentMethod() );
}
/**
* Evaluate the body if current class has a method with the specified
* name+parameters. If parameters not specified then any method with the given
* name and any set of parameters is considered equal to the given method name
* and so the test result is positive and the body is evaluated. This method
* does not change the current method to the one specified.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @see
#ifDoesntHaveMethod(java.lang.String,java.util.Properties)
* @doc:tag type="block"
* @doc:param name="name" optional="false" description="The
* name of the method we're searching for its existence in current class."
* @doc:param name="parameters" optional="true"
* description="We're searching for a method that has the exact set of
* parameters specified in parameters param."
* @doc:param name="delimiter" optional="true"
* description="The parameters param is delimited by the string specified
* in delimiter parameter."
*/
public void ifHasMethod( String template, Properties attributes ) throws
XDocletException
{
ifHasMethod_Impl( template, attributes, true );
}
/**
* Evaluate the body if current class doesn't have a method with the specified
* name+parameters. If parameters not specified then any method with the given
* name and any set of parameters is considered equal to the given method name
* and so the test result is positive and the body is evaluated.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException Description of Exception
* @see
#ifHasMethod(java.lang.String,java.util.Properties)
* @doc:tag type="block"
* @doc:param name="name" optional="false" description="The
* name of the method we're searching for its existence in current class."
* @doc:param name="parameters" optional="true"
* description="We're searching for a method that has the exact set of
* parameters specified in parameters param."
* @doc:param name="delimiter" optional="true"
* description="The parameters param is delimited by the string specified
* in delimiter parameter."
*/
public void ifDoesntHaveMethod( String template, Properties attributes )
throws XDocletException
{
ifHasMethod_Impl( template, attributes, false );
}
/**
* Searches for the MethodDoc of the method with name methodName and returns
* it.
*
* @param methodName Description of Parameter
* @return The MethodDocForMethodName value
*/
protected MethodDoc getMethodDocForMethodName( String methodName )
{
if( methodName != null )
return extractMethodDoc( getCurrentClass(), methodName );
return null;
}
/**
* Searches for the MethodDoc of the method with name methodName and returns
* it.
*
* @param methodName The method to return MethodDoc for.
* @param superclasses Search superclasses.
* @return The MethodDoc for the method named value
*/
protected MethodDoc getMethodDocForMethodName( String methodName, boolean
superclasses )
{
if( !superclasses )
return getMethodDocForMethodName( methodName );
for( ClassDoc clazz = getCurrentClass(); clazz != null; clazz =
clazz.superclass() )
{
MethodDoc method = extractMethodDoc( clazz, methodName );
if( method != null )
return method;
}
return null;
}
/**
* Returns true if a method with the specified methodName+parameters is found
* in the class clazz. The parameters array can be empty, if so any method with
* any set of parameters is considered equal to the method we're searching for.
* if not empty all parameters of the method must be equal to the ones
* specified in parameters array to have "method equality".
*
* @param clazz Description of Parameter
* @param methodName Description of Parameter
* @param parameters Description of Parameter
* @param setCurrentMethod Description of Parameter
* @return Description of the Returned Value
*/
protected boolean hasMethod( ClassDoc clazz, String methodName, String[]
parameters, boolean setCurrentMethod )
{
Category cat = Log.getCategory( MethodTagsHandler.class, "hasMethod" );
if( cat.isDebugEnabled() )
cat.debug( "Search for method " + methodName + " in " +
clazz.name() );
while( clazz != null )
{
MethodDoc[] methods = clazz.methods();
methodLoop :
for( int i = 0; i < methods.length; i++ )
{
if( methods[i].name().equals( methodName ) )
{
// All parameters must be equal to have
"method equality"
Parameter[] params = methods[i].parameters();
if( parameters == null )
{
// The class has the given method
if( setCurrentMethod )
setCurrentMethod( methods[i] );
return true;
}
if( parameters != null && params == null )
continue methodLoop;
if( parameters.length != params.length )
continue methodLoop;
for( int j = 0; j < params.length; j++ )
{
if( !params[j].typeName().equals(
parameters[j] ) )
continue methodLoop;
}
// we have to handle the inverse order as well
for( int j = 0; j < parameters.length; j++ )
{
if( !params[j].typeName().equals(
parameters[j] ) )
continue methodLoop;
}
if( cat.isDebugEnabled() )
cat.debug( "Method found in " +
clazz.name() );
// The class has the given method
if( setCurrentMethod )
setCurrentMethod( methods[i] );
return true;
}
}
// Check super class info
clazz = clazz.superclass();
}
if( cat.isDebugEnabled() )
cat.debug( "Method not found" );
return false;
}
private boolean isInAppendExceptionsList( String append_exceptions, String
type )
{
if( append_exceptions == null )
return false;
else
return append_exceptions.indexOf( type ) != -1;
}
private boolean isInSkipExceptionsList( String skip_exceptions, String type )
{
if( skip_exceptions == null )
return false;
else
return skip_exceptions.indexOf( type ) != -1;
}
private MethodDoc extractMethodDoc( ClassDoc clazz, String methodName )
{
MethodDoc[] methods = clazz.methods();
for( int i = 0; i < methods.length; i++ )
{
if( methods[i].name().equals( methodName ) )
return methods[i];
}
return null;
}
private void appendException( StringBuffer st, String type )
{
if( st.length() == 0 )
st.append( "throws " );
else
st.append( ", " );
st.append( type );
}
/**
* The implementation of ifHasMethod and ifDoesntHaveMethod tags.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @param has_method Description of Parameter
* @exception XDocletException Description of Exception
* @see
#ifHasMethod(java.lang.String,java.util.Properties)
* @see
#ifDoesntHaveMethod(java.lang.String,java.util.Properties)
* @see
#hasMethod(com.sun.javadoc.ClassDoc,java.lang.String,java.lang.String[],boolean)
*/
private void ifHasMethod_Impl( String template, Properties attributes, boolean
has_method ) throws XDocletException
{
Category cat = Log.getCategory( MethodTagsHandler.class,
"ifHasMethod_Impl" );
String methodName = attributes.getProperty( "name" );
String parametersStr = attributes.getProperty( "parameters" );
String delimiter = attributes.getProperty( "delimiter" );
String[] parameters = null;
if( cat.isDebugEnabled() )
{
cat.debug( "methodName=" + methodName );
cat.debug( "parametersStr=" + parametersStr );
cat.debug( "delimiter=" + delimiter );
cat.debug( "has_method=" + has_method );
cat.debug( "getCurrentClass()=" + getCurrentClass() );
}
if( parametersStr != null )
{
if( delimiter == null )
delimiter = PARAMETER_DELIMITER;
parameters = DocletUtil.tokenizeDelimitedToArray(
parametersStr, delimiter );
if( cat.isDebugEnabled() )
{
cat.debug( "parameters.length=" + parameters.length );
cat.debug( "parameters[0]=" + parameters[0] );
}
}
if( hasMethod( getCurrentClass(), methodName, parameters, false ) ==
has_method )
{
if( cat.isDebugEnabled() )
cat.debug( "method found." );
generate( template );
}
else
{
if( cat.isDebugEnabled() )
cat.debug( "method not found." );
}
}
}