/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.lang.Param;
import gw.lang.Returns;
import gw.lang.Throws;
import gw.lang.parser.ITypeUsesMap;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.ICompilableType;
import gw.util.GosuStringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DocCommentBlock
{
private List<DocAnnotationData> _annotationData = null;
private StringBuilder _desc;
private ITypeUsesMap _typeUsesMap;
private ICompilableType _ownersType;
private String _rawComment;
private boolean computeAnnotationData = false;
public void setRawComment(String rawComment) {
_rawComment = rawComment;
computeAnnotationData = true;
}
private void addLine( String line )
{
String strippedLine = stripLeadingCommentAndWhiteSpace( line );
DocAnnotationData annotationData = maybeStartDocAnnotation( strippedLine );
if( annotationData != null )
{
if( _annotationData == null )
{
_annotationData = new ArrayList<DocAnnotationData>();
}
_annotationData.add( annotationData );
}
else if( _annotationData == null )
{
if( _desc == null )
{
_desc = new StringBuilder();
_desc.append( strippedLine );
}
else
{
_desc.append( "\n" );
_desc.append( strippedLine );
}
}
else
{
_annotationData.get( _annotationData.size() - 1 ).getArg().append("\n").append( strippedLine );
}
}
public String getDescription()
{
if(computeAnnotationData)
{
computeAnnotationData();
computeAnnotationData = false;
}
return GosuStringUtil.strip( _desc == null ? "" : _desc.toString() );
}
public List<IGosuAnnotation> getAnnotations()
{
if(computeAnnotationData)
{
computeAnnotationData();
computeAnnotationData = false;
}
if( _annotationData == null )
{
return Collections.emptyList();
}
ArrayList<IGosuAnnotation> lst = new ArrayList<IGosuAnnotation>( _annotationData.size() );
for( DocAnnotationData annotation : _annotationData )
{
IGosuAnnotation gosuAnnotation = annotation.makeAnnotation( _ownersType, _typeUsesMap );
if( gosuAnnotation != null )
{
lst.add( gosuAnnotation );
}
}
return lst;
}
private void computeAnnotationData() {
final String[] lines = _rawComment.substring( 2, _rawComment.length()-2 ).split( "\n" );
for(String line : lines)
{
addLine( line );
}
}
private DocAnnotationData maybeStartDocAnnotation( String line )
{
Class annotationClass = null;
// from http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#javadoctags
if( line.startsWith( "@deprecated" ) )
{
annotationClass = gw.lang.Deprecated.class;
}
else if( line.startsWith( "@exception" ) )
{
annotationClass = Throws.class;
}
else if( line.startsWith( "@param" ) )
{
annotationClass = Param.class;
}
else if( line.startsWith( "@return" ) )
{
annotationClass = Returns.class;
}
else if( line.startsWith( "@throws" ) )
{
annotationClass = Throws.class;
}
if( annotationClass != null )
{
int i = line.indexOf( " " );
return new DocAnnotationData( annotationClass, i == -1 ? "" : line.substring( i ) );
}
else
{
return null;
}
}
private String stripLeadingCommentAndWhiteSpace( String line )
{
String s = "";
for( int i = 0; i < line.length(); i++ )
{
if( !isBlankOrCommentChar( line.charAt( i ) ) )
{
s = line.substring( i );
break;
}
}
return s.trim();
}
private boolean isBlankOrCommentChar( char c )
{
return c == ' ' || c == '\t' || c == '*';
}
public void setOwnersTypes( ICompilableType ownersType )
{
_ownersType = ownersType;
_typeUsesMap = _ownersType == null ? null : _ownersType.getTypeUsesMap();
}
private static class DocAnnotationData
{
private Class _class;
private StringBuilder _arg;
public StringBuilder getArg()
{
return _arg;
}
DocAnnotationData( Class type, String arg )
{
_class = type;
_arg = new StringBuilder( arg );
}
public IGosuAnnotation makeAnnotation( ICompilableType ownersType, ITypeUsesMap typeUses )
{
String[] args = makeArgs();
if( _class == Throws.class )
{
try
{
IType iType = TypeSystem.getByRelativeName( args[0], typeUses );
args[0] = iType.getName();
}
catch( ClassNotFoundException e )
{
return null;
}
}
return new GosuDocAnnotation( ownersType, TypeSystem.get( _class ), args );
}
private String[] makeArgs()
{
String arg = GosuStringUtil.strip( GosuStringUtil.strip( _arg.toString() ) );
if( _class == Throws.class || _class == Param.class )
{
return splitFirstArg( arg );
}
else
{
return new String[]{arg};
}
}
private String[] splitFirstArg( String arg )
{
String[] args = arg.split("\\s+", 2);
if (args.length == 1) { // no description
args = new String[] { arg, "" };
}
return args;
}
}
@Override
public String toString()
{
return "DocCommentBlock(" + getDescription() + ")";
}
}