package de.unisiegen.tpml.core.latex ;
import java.util.ArrayList ;
import de.unisiegen.tpml.core.prettyprinter.PrettyCommandNames ;
/**
* Default implementation of the <code>LatexStringBuilder</code> interface,
* which is the heart of the latex printer.
*
* @author Christian Fehler
* @see LatexStringBuilder
* @see LatexStringBuilderFactory
*/
public final class DefaultLatexStringBuilder implements LatexStringBuilder ,
PrettyCommandNames
{
/**
* Returns a string only with spaces. The count of the returned spaces is
* <code>pIdent</code>.
*
* @param pIndent The number of spaces.
* @return A string only with spaces. The count of the returned spaces is
* <code>pIdent</code>.
*/
public static String getIndent ( int pIndent )
{
StringBuilder result = new StringBuilder ( ) ;
for ( int i = 0 ; i < pIndent ; i ++ )
{
result.append ( " " ) ; //$NON-NLS-1$
}
return result.toString ( ) ;
}
/**
* The items already added to this latex string builder.
*
* @see AbstractLatexItem
*/
private ArrayList < AbstractLatexItem > items = new ArrayList < AbstractLatexItem > ( ) ;
/**
* The return priority of the printable according to the priority grammar.
*/
private int returnPriority ;
/**
* The indent of this object.
*/
private int indent ;
/**
* The array of parameter descriptions.
*/
private String [ ] parameterDescriptions ;
/**
* The child parameter count.
*/
private int parameterCount = 0 ;
/**
* Allocates a new <code>DefaultLatextringBuilder</code> for the
* <code>printable</code>, where the priority used for the
* <code>printable</code> is <code>returnPriority</code>.
*
* @param pReturnPriority The priority for the <code>printable</code>,
* which determines where and when to add parenthesis around
* {@link LatexPrintable}s added to this builder.
* @param pIndent The indent of this object.
* @param pParameterDescriptions The array of parameter descriptions.
* @throws NullPointerException if <code>printable</code> is
* <code>null</code>.
*/
public DefaultLatexStringBuilder ( int pReturnPriority , int pIndent ,
String ... pParameterDescriptions )
{
this.returnPriority = pReturnPriority ;
this.indent = pIndent ;
this.parameterDescriptions = pParameterDescriptions ;
addParameterDescription ( ) ;
}
/**
* Allocates a new <code>DefaultLatextringBuilder</code> for the
* <code>printable</code>, where the priority used for the
* <code>printable</code> is <code>returnPriority</code>.
*
* @param pReturnPriority The priority for the <code>printable</code>,
* which determines where and when to add parenthesis around
* {@link LatexPrintable}s added to this builder.
* @param pName The name of this latex command.
* @param pIndent The indent of this object.
* @param pParameterDescriptions The array of parameter descriptions.
* @throws NullPointerException if <code>printable</code> is
* <code>null</code>.
*/
public DefaultLatexStringBuilder ( int pReturnPriority , String pName ,
int pIndent , String ... pParameterDescriptions )
{
this ( pReturnPriority , pIndent , pParameterDescriptions ) ;
this.items
.add ( new TextLatexItem ( getIndent ( pIndent ) + "\\" + pName ) ) ; //$NON-NLS-1$
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addBreak()
*/
public void addBreak ( )
{
this.items.add ( new BreakLatexItem ( ) ) ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addBuilder(LatexStringBuilder, int)
*/
public void addBuilder ( LatexStringBuilder pLatexStringBuilder ,
int pArgumentPriority )
{
if ( pLatexStringBuilder == null )
{
throw new NullPointerException ( "builder is null" ) ; //$NON-NLS-1$
}
DefaultLatexStringBuilder defaultBuilder = ( DefaultLatexStringBuilder ) pLatexStringBuilder ;
boolean breakItem = false ;
if ( this.items.get ( this.items.size ( ) - 1 ) instanceof BreakLatexItem )
{
this.items.remove ( this.items.size ( ) - 1 ) ;
breakItem = true ;
}
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
addParameterDescription ( ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent ) + "{" ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
if ( breakItem )
{
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "\\linebreak[3]" ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
}
boolean parenthesis = ( defaultBuilder.returnPriority < pArgumentPriority ) ;
if ( parenthesis )
{
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "\\" + LATEX_PARENTHESIS ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "{" ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new BuilderLatexItem ( defaultBuilder ) ) ;
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "}" ) ) ; //$NON-NLS-1$
}
else
{
this.items.add ( new BuilderLatexItem ( defaultBuilder ) ) ;
}
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent ) + "}" ) ) ; //$NON-NLS-1$
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addBuilderBegin()
*/
public void addBuilderBegin ( )
{
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
addParameterDescription ( ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent ) + "{" ) ) ; //$NON-NLS-1$
this.indent = this.indent + LATEX_INDENT ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addBuilderEnd()
*/
public void addBuilderEnd ( )
{
this.indent = this.indent - LATEX_INDENT ;
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent ) + "}" ) ) ; //$NON-NLS-1$
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addBuilderWithoutBrackets(LatexStringBuilder, int)
*/
public void addBuilderWithoutBrackets (
LatexStringBuilder pLatexStringBuilder , int pArgumentPriority )
{
if ( pLatexStringBuilder == null )
{
throw new NullPointerException ( "builder is null" ) ; //$NON-NLS-1$
}
DefaultLatexStringBuilder defaultBuilder = ( DefaultLatexStringBuilder ) pLatexStringBuilder ;
boolean breakItem = false ;
if ( this.items.get ( this.items.size ( ) - 1 ) instanceof BreakLatexItem )
{
this.items.remove ( this.items.size ( ) - 1 ) ;
breakItem = true ;
}
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
if ( breakItem )
{
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "\\linebreak[3]" ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
}
boolean parenthesis = ( defaultBuilder.returnPriority < pArgumentPriority ) ;
if ( parenthesis )
{
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "\\" + LATEX_PARENTHESIS ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "{" ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new BuilderLatexItem ( defaultBuilder ) ) ;
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent
+ LATEX_INDENT )
+ "}" ) ) ; //$NON-NLS-1$
}
else
{
this.items.add ( new BuilderLatexItem ( defaultBuilder ) ) ;
}
this.parameterCount ++ ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addComment(String)
*/
public void addComment ( String pText )
{
this.items.add ( new TextLatexItem ( "% " + pText ) ) ; //$NON-NLS-1$
addSourceCodeBreak ( 0 ) ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addEmptyBuilder()
*/
public void addEmptyBuilder ( )
{
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
addParameterDescription ( ) ;
this.items.add ( new TextLatexItem ( getIndent ( this.indent ) + "{}" ) ) ; //$NON-NLS-1$
}
/**
* Adds the parameter description to the source code.
*/
private void addParameterDescription ( )
{
if ( this.parameterCount < this.parameterDescriptions.length )
{
this.items.add ( new TextLatexItem ( getIndent ( this.indent )
+ "% " //$NON-NLS-1$
+ this.parameterDescriptions [ this.parameterCount ].replaceAll (
PRETTY_LINE_BREAK , PRETTY_LINE_BREAK + getIndent ( this.indent )
+ "% " ) ) ) ; //$NON-NLS-1$
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
}
this.parameterCount ++ ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addSourceCodeBreak(int)
*/
public void addSourceCodeBreak ( int pIndentOffset )
{
this.items.add ( new TextLatexItem ( LATEX_LINE_BREAK_SOURCE_CODE ) ) ;
this.items.add ( new TextLatexItem ( DefaultLatexStringBuilder
.getIndent ( this.indent + pIndentOffset ) ) ) ;
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#addText(String)
*/
public void addText ( String pText )
{
this.items.add ( new TextLatexItem ( pText ) ) ;
}
/**
* Determines the string representation of this builders contents and adds it
* to the <code>pBuffer</code>.
*
* @param pBuffer String buffer to store the characters to.
* @param pIndent The indent of this object.
*/
public void determineString ( StringBuilder pBuffer , int pIndent )
{
for ( AbstractLatexItem item : this.items )
{
item.determineString ( pBuffer , pIndent ) ;
}
}
/**
* {@inheritDoc}
*
* @see LatexStringBuilder#toLatexString()
*/
public LatexString toLatexString ( )
{
StringBuilder buffer = new StringBuilder ( ) ;
determineString ( buffer , this.indent ) ;
return new DefaultLatexString ( buffer.toString ( ) ) ;
}
}