package de.unisiegen.tpml.graphics.components ;
import java.util.ArrayList ;
import de.unisiegen.tpml.core.expressions.Expression ;
import de.unisiegen.tpml.core.expressions.Identifier ;
import de.unisiegen.tpml.core.interfaces.BoundIdentifiers ;
import de.unisiegen.tpml.core.interfaces.BoundTypeNames ;
import de.unisiegen.tpml.core.interfaces.DefaultTypes ;
import de.unisiegen.tpml.core.interfaces.ShowBondsInput ;
import de.unisiegen.tpml.core.prettyprinter.PrettyAnnotation ;
import de.unisiegen.tpml.core.typeinference.TypeEquationTypeInference ;
import de.unisiegen.tpml.core.typeinference.TypeSubType ;
import de.unisiegen.tpml.core.types.MonoType ;
import de.unisiegen.tpml.core.types.Type ;
import de.unisiegen.tpml.core.types.TypeName ;
/**
* Calculates the bound {@link Identifier}s.
*
* @author Benjamin Mies
* @author Christian Fehler
*/
public final class ShowBonds
{
/**
* The loaded {@link ShowBondsInput}.
*/
private ShowBondsInput loaded = null ;
/**
* List of all Bonds in loaded {link Expression}.
*/
private ArrayList < Bonds > result = null ;
/**
* Checks the given {@link Expression} for bound {@link Identifier}s.
*
* @param pExpression The input {@link Expression}.
*/
private final void check ( Expression pExpression )
{
if ( pExpression instanceof BoundIdentifiers )
{
Identifier [ ] id = ( ( BoundIdentifiers ) pExpression )
.getIdentifiers ( ) ;
ArrayList < ArrayList < Identifier >> bound = ( ( BoundIdentifiers ) pExpression )
.getIdentifiersBound ( ) ;
// Create Bonds
if ( bound == null )
{
return ;
}
PrettyAnnotation current ;
for ( int i = 0 ; i < bound.size ( ) ; i ++ )
{
if ( bound.get ( i ) == null )
{
continue ;
}
current = this.loaded.toPrettyString ( ).getAnnotationForPrintable (
id [ i ] ) ;
Bonds bonds = new Bonds ( current.getStartOffset ( ) , current
.getEndOffset ( ) ) ;
for ( Identifier boundId : bound.get ( i ) )
{
try
{
bonds.addPrettyAnnotation ( this.loaded.toPrettyString ( )
.getAnnotationForPrintable ( boundId ) ) ;
}
catch ( IllegalArgumentException e )
{
/*
* Happens if a bound Identifier is not in the PrettyString. For
* example "object (self) val a = 0 ; method move = {< a = 2 >} ;
* end". The "self" binds the free Identifier "self" in the
* Duplication (method free in Duplication), but the free "self" in
* the Duplication is not present in the PrettyString.
*/
}
}
this.result.add ( bonds ) ;
}
}
if ( pExpression instanceof DefaultTypes )
{
MonoType [ ] types = ( ( DefaultTypes ) pExpression ).getTypes ( ) ;
for ( MonoType tau : types )
{
if ( tau != null )
{
check ( tau ) ;
}
}
}
for ( Expression expr : pExpression.children ( ) )
{
check ( expr ) ;
}
}
/**
* Checks the given {@link Type} for bound {@link TypeName}s.
*
* @param pType The input {@link Type}.
*/
private final void check ( Type pType )
{
if ( pType instanceof BoundTypeNames )
{
TypeName [ ] typeNames = ( ( BoundTypeNames ) pType ).getTypeNames ( ) ;
ArrayList < ArrayList < TypeName >> bound = ( ( BoundTypeNames ) pType )
.getTypeNamesBound ( ) ;
// Create Bonds
if ( bound == null )
{
return ;
}
PrettyAnnotation current ;
for ( int i = 0 ; i < bound.size ( ) ; i ++ )
{
if ( bound.get ( i ) == null )
{
continue ;
}
current = this.loaded.toPrettyString ( ).getAnnotationForPrintable (
typeNames [ i ] ) ;
Bonds bonds = new Bonds ( current.getStartOffset ( ) , current
.getEndOffset ( ) ) ;
for ( TypeName boundTypeNames : bound.get ( i ) )
{
try
{
bonds.addPrettyAnnotation ( this.loaded.toPrettyString ( )
.getAnnotationForPrintable ( boundTypeNames ) ) ;
}
catch ( IllegalArgumentException e )
{
/*
* Happens if a bound TypeName is not in the PrettyString.
*/
}
}
this.result.add ( bonds ) ;
}
}
for ( Type tau : pType.children ( ) )
{
check ( tau ) ;
}
}
/**
* Returns a list with all bonds in the loaded {@link Expression}.
*
* @return A list with all bonds in the loaded {@link Expression}.
*/
public final ArrayList < Bonds > getAnnotations ( )
{
if ( this.result == null )
{
this.result = new ArrayList < Bonds > ( ) ;
if ( this.loaded != null )
{
if ( this.loaded instanceof Expression )
{
check ( ( Expression ) this.loaded ) ;
}
else if ( this.loaded instanceof Type )
{
check ( ( Type ) this.loaded ) ;
}
else if ( this.loaded instanceof TypeEquationTypeInference )
{
check ( ( ( TypeEquationTypeInference ) this.loaded ).getLeft ( ) ) ;
check ( ( ( TypeEquationTypeInference ) this.loaded ).getRight ( ) ) ;
}
else if ( this.loaded instanceof TypeSubType )
{
check ( ( ( TypeSubType ) this.loaded ).getType ( ) ) ;
check ( ( ( TypeSubType ) this.loaded ).getType2 ( ) ) ;
}
}
}
return this.result ;
}
/**
* Loads the {@link ShowBondsInput} to get the bonds.
*
* @param pLoaded The input {@link ShowBondsInput}.
*/
public final void load ( ShowBondsInput pLoaded )
{
this.loaded = pLoaded ;
}
/**
* {@inheritDoc} Mainly useful for debugging purposes.
*
* @see Object#toString()
*/
@ Override
public final String toString ( )
{
if ( this.result == null )
{
return "" ; //$NON-NLS-1$
}
String s = "" ; //$NON-NLS-1$
for ( Bonds item : this.result )
{
s += item + "\n" ; //$NON-NLS-1$
}
return s ;
}
}