/*==========================================================================*\
| $Id: TestOptions.java,v 1.3 2010/02/23 17:19:18 stedwar2 Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2006-2010 Virginia Tech
|
| This file is part of Web-CAT.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation; either version 2 of the License, or
| (at your option) any later version.
|
| Web-CAT is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with Web-CAT; if not, write to the Free Software
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
| Project manager: Stephen Edwards <edwards@cs.vt.edu>
| Virginia Tech CS Dept, 660 McBryde Hall (0106), Blacksburg, VA 24061 USA
\*==========================================================================*/
package net.sf.webcat.plugins.javatddplugin;
import junit.framework.Test;
//-------------------------------------------------------------------------
/**
* Manages the various options controlling default hint generation for
* a specific method.
*
* @author Stephen Edwards
* @author Last changed by $Author: stedwar2 $
* @version $Revision: 1.3 $, $Date: 2010/02/23 17:19:18 $
*/
public class TestOptions
extends HintOptions
{
//~ Constructors ..........................................................
// ----------------------------------------------------------
/**
* Create a HintOptions object that inherits defaults from another
* HintOptions object.
* @param suite the object representing options for the enclosing class
* @param test the test that this object contains options for
*/
public TestOptions( TestSuiteOptions suite, Test test )
{
super( suite );
this.test = test;
loadFromAnnotations();
}
//~ Public Methods ........................................................
// ----------------------------------------------------------
/**
* Get the test case.
* @return the case
*/
public Test test()
{
return test;
}
// ----------------------------------------------------------
/**
* Get the method name associated with this test.
* @return the method name
*/
public String methodName()
{
if ( methodName == null && test != null )
{
methodName = test.toString();
if ( methodName != null )
{
// Strip the class name from the end of the test case name
int pos = methodName.indexOf( '(' );
if ( pos > 0 )
{
methodName = methodName.substring( 0, pos );
}
}
}
return methodName;
}
// ----------------------------------------------------------
public String hint()
{
if ( hasNoLocalHint() && !onlyExplicitHints() )
{
setHint( hintFromMethodName( methodName() ) );
}
return super.hint();
}
//~ Private Methods .......................................................
// ----------------------------------------------------------
private void loadFromAnnotations()
{
Class<?> suiteClass = ( parent() == null )
? null
: ((TestSuiteOptions)parent()).suiteClass();
if ( suiteClass == null )
{
return;
}
String name = methodName();
if ( name == null )
{
return;
}
java.lang.reflect.Method method = null;
try
{
method = suiteClass.getMethod( name, (Class[])null );
}
catch ( NoSuchMethodException e )
{
// Ignore this one
}
if ( method != null )
{
loadFromAnnotations( method );
}
}
// ----------------------------------------------------------
private String hintFromMethodName( String aMethodName )
{
String result = aMethodName;
if ( result != null )
{
// Remove "test" from the start
if ( result.length() > 4
&& result.startsWith( "test" )
&& ( !Character.isLetter( result.charAt( 4 ) )
|| Character.isUpperCase( result.charAt( 4 ) ) ) )
{
result = result.substring( 4 );
}
// Remove any trailing digits not preceded by an underscore
result = result.replaceFirst( "(?<!_)[0-9]+$", "" );
// Now split into phrases using underscores
StringBuffer sb = new StringBuffer();
for ( String phrase : result.replace("__", "_._").split( "_" ) )
{
if ( phrase != null && !phrase.equals( "" ) )
{
String thisPhrase = translateWordPhrase( phrase );
if (".".equals(thisPhrase))
{
// Don't put spaces around it
int lastPos = sb.length() - 1;
if ( lastPos >= 0 && sb.charAt( lastPos ) == ' ' )
{
sb.deleteCharAt( lastPos );
}
sb.append( translateWordPhrase( phrase ) );
}
else
{
sb.append( translateWordPhrase( phrase ) );
sb.append( ' ' );
}
}
}
if ( sb.length() > 0 )
{
sb.deleteCharAt( sb.length() - 1 );
}
result = sb.toString();
}
return result;
}
// ----------------------------------------------------------
private String translateWordPhrase( String word )
{
String result = word;
// First, look for method
if ( result.length() > 1
&& result.charAt( 0 ) == 'c'
&& Character.isUpperCase( result.charAt( 1 ) ) )
{
result = result.substring( 1 );
}
// Second, look for method
else if ( result.length() > 1
&& result.charAt( 0 ) == 'm'
&& Character.isUpperCase( result.charAt( 1 ) ) )
{
result = Character.toLowerCase( result.charAt( 1 ) )
+ result.substring( 2 ) + "()";
}
// Then look for all uppercase
else if ( isUpperCase( word ) )
{
// Do nothing
}
// Then split on caps and convert to lower case
else
{
StringBuffer sb = new StringBuffer();
for ( String wd : word.split( WORD_BOUNDARY_REGEX ) )
{
if ( wd != null && !"".equals( wd ) )
{
if ( isUpperCase( wd ) )
{
sb.append( wd );
}
else
{
sb.append( wd.toLowerCase() );
}
sb.append( ' ' );
}
}
if ( sb.length() > 0 )
{
sb.deleteCharAt( sb.length() - 1 );
}
result = sb.toString();
}
return result;
}
// ----------------------------------------------------------
private boolean isUpperCase( String word )
{
int length = word.length();
for( int i = 0; i < length; i++ )
{
char c = word.charAt( i );
if ( !Character.isUpperCase( c ) && !Character.isDigit( c ) )
{
return false;
}
}
return true;
}
//~ Instance/static variables .............................................
private Test test;
private String methodName;
private static final String WORD_BOUNDARY_REGEX =
"((?<=[^\\p{javaUpperCase}])(?=\\p{javaUpperCase}))"
+ "|((?<=\\p{javaUpperCase})(?=\\p{javaUpperCase}[^\\p{Upper}]))";
// Originally, this was:
// "((?<=[^A-Z])(?=[A-Z]))|((?<=[A-Z])(?=[A-Z][^A-Z]))"
// But it was changed so it would work with other languages more
// effectively. Unfortunately, I had to use Upper instead of
// javaUpperCase in the very last character class--otherwise, it
// triggered a bug in Java's regular expression package when splitting
// a string containing a sequence of multiple upper case letters at
// the end.
}