package de.unisiegen.tpml.core.expressions ; import java.util.ArrayList ; import de.unisiegen.tpml.core.exceptions.NotOnlyFreeVariableException ; import de.unisiegen.tpml.core.interfaces.DefaultIdentifiers ; import de.unisiegen.tpml.core.interfaces.IdentifierOrTypeName ; import de.unisiegen.tpml.core.latex.DefaultLatexCommand ; import de.unisiegen.tpml.core.latex.LatexCommandList ; import de.unisiegen.tpml.core.latex.LatexStringBuilder ; import de.unisiegen.tpml.core.latex.LatexStringBuilderFactory ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilder ; import de.unisiegen.tpml.core.prettyprinter.PrettyStringBuilderFactory ; /** * Represents an identifier in the expression hierarchy. Identifiers are values * in the semantics of the various languages. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev:1056 $ * @see Value */ public final class Identifier extends Value implements IdentifierOrTypeName { /** * The set of {@link Identifier}s. * * @author Christian Fehler */ public enum Set { /** * The set of variable {@link Identifier}s. */ VARIABLE , /** * The set of attribute {@link Identifier}s. */ ATTRIBUTE , /** * The set of method {@link Identifier}s. */ METHOD , /** * The set of self {@link Identifier}s. */ SELF } /** * The caption of this {@link Expression}. */ private static final String CAPTION = Expression .getCaption ( Identifier.class ) ; /** * String for the case that the name is null. */ private static final String NAME_NULL = "name is null" ; //$NON-NLS-1$ /** * String for the case that the set is null. */ private static final String SET_NULL = "set is null" ; //$NON-NLS-1$ /** * Returns a set of needed latex commands for this latex printable object. * * @return A set of needed latex commands for this latex printable object. */ public static LatexCommandList getLatexCommandsStatic ( ) { LatexCommandList commands = new LatexCommandList ( ) ; commands.add ( new DefaultLatexCommand ( LATEX_IDENTIFIER , 1 , "\\mbox{\\color{" + LATEX_COLOR_IDENTIFIER + "}{#1}}" , "id" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ commands.add ( new DefaultLatexCommand ( LATEX_IDENTIFIER_BINDING , 1 , "\\mbox{\\textbf{\\color{" + LATEX_COLOR_BINDING_ID + "}{#1}}}" , "id" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ commands.add ( new DefaultLatexCommand ( LATEX_IDENTIFIER_BOUND , 1 , "\\mbox{\\textbf{\\color{" + LATEX_COLOR_BOUND_ID + "}{#1}}}" , "id" ) ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return commands ; } /** * The {@link Expression} in which this {@link Identifier} is bound. * * @see #getBoundToExpression() * @see #setBoundTo(Expression,Identifier) */ private Expression boundToExpression = null ; /** * The {@link Identifier} to which this {@link Identifier} is bound. * * @see #getBoundToIdentifier() * @see #setBoundTo(Expression,Identifier) */ private Identifier boundToIdentifier = null ; /** * The name of the {@link Identifier}. */ private String name ; /** * The set of this {@link Identifier}. * * @see #getSet() * @see #setSet(Set) */ private Set set ; /** * Allocates a new {@link Identifier} with the given <code>name</code>. * * @param pName the name of the identifier. * @param pSet The set of this {@link Identifier}. */ public Identifier ( String pName , Set pSet ) { if ( pName == null ) { throw new NullPointerException ( NAME_NULL ) ; } if ( pSet == null ) { throw new NullPointerException ( SET_NULL ) ; } this.name = pName ; this.set = pSet ; } /** * Allocates a new {@link Identifier} with the given <code>name</code>. * * @param pName the name of the identifier. * @param pSet The set of this {@link Identifier}. * @param pParserStartOffset The start offset of this {@link Expression} in * the source code. * @param pParserEndOffset The end offset of this {@link Expression} in the * source code. */ public Identifier ( String pName , Set pSet , int pParserStartOffset , int pParserEndOffset ) { this ( pName , pSet ) ; this.parserStartOffset = pParserStartOffset ; this.parserEndOffset = pParserEndOffset ; } /** * {@inheritDoc} * * @see Expression#clone() */ @ Override public final Identifier clone ( ) { return new Identifier ( this.name , this.set ) ; } /** * {@inheritDoc} * * @see Expression#equals(Object) */ @ Override public final boolean equals ( Object obj ) { if ( obj instanceof Identifier ) { Identifier other = ( Identifier ) obj ; return this.name.equals ( other.name ) ; } return false ; } /** * Returns the {@link Expression} in which this {@link Identifier} is bound. * * @return The {@link Expression} in which this {@link Identifier} is bound. * @see #boundToExpression * @see #setBoundTo(Expression,Identifier) */ public final Expression getBoundToExpression ( ) { return this.boundToExpression ; } /** * Returns the {@link Identifier} to which this {@link Identifier} is bound. * * @return The {@link Identifier} to which this {@link Identifier} is bound. * @see #boundToIdentifier * @see #setBoundTo(Expression,Identifier) */ public final Identifier getBoundToIdentifier ( ) { return this.boundToIdentifier ; } /** * {@inheritDoc} */ @ Override public final String getCaption ( ) { return CAPTION ; } /** * Returns a set that contains exacty one element, which is the name of the * identifier. * * @return a set which contains the name of the identifier. * @see Expression#getIdentifiersFree() */ @ Override public final ArrayList < Identifier > getIdentifiersFree ( ) { if ( this.identifiersFree == null ) { this.identifiersFree = new ArrayList < Identifier > ( ) ; this.identifiersFree.add ( this ) ; } return this.identifiersFree ; } /** * Returns a set of needed latex commands for this latex printable object. * * @return A set of needed latex commands for this latex printable object. */ @ Override public LatexCommandList getLatexCommands ( ) { LatexCommandList commands = super.getLatexCommands ( ) ; commands.add ( getLatexCommandsStatic ( ) ) ; return commands ; } /** * Returns the prefix of this {@link Expression}. * * @return The prefix of this {@link Expression}. * @see #prefix */ @ Override public final String getPrefix ( ) { if ( this.prefix == null ) { if ( ( this.parent != null ) && ( this.parent instanceof DefaultIdentifiers ) ) { Identifier [ ] identifiers = ( ( DefaultIdentifiers ) this.parent ) .getIdentifiers ( ) ; for ( Identifier id : identifiers ) { if ( id == this ) { switch ( this.set ) { case VARIABLE : { this.prefix = PREFIX_ID_V ; return this.prefix ; } case ATTRIBUTE : { this.prefix = PREFIX_ID_A ; return this.prefix ; } case METHOD : { this.prefix = PREFIX_ID_M ; return this.prefix ; } case SELF : { this.prefix = PREFIX_ID_S ; return this.prefix ; } } } } } this.prefix = PREFIX_VALUE ; } return this.prefix ; } /** * Returns the set of this {@link Identifier}. * * @return The set of this {@link Identifier}. * @see #set * @see #setSet(Set) */ public final Set getSet ( ) { return this.set ; } /** * {@inheritDoc} * * @see Expression#hashCode() */ @ Override public final int hashCode ( ) { return this.name.hashCode ( ) ; } /** * Sets the {@link Identifier} to which this {@link Identifier} is bound and * the {@link Expression} in which this {@link Identifier} is bound. * * @param pBoundToExpression The {@link Expression} in which this * {@link Identifier} is bound. * @param pBoundToIdentifier The {@link Identifier} to which this * {@link Identifier} is bound. * @see #boundToIdentifier * @see #getBoundToIdentifier() */ public final void setBoundTo ( Expression pBoundToExpression , Identifier pBoundToIdentifier ) { if ( ( this.boundToIdentifier != null ) && ( this.boundToIdentifier != pBoundToIdentifier ) ) { System.err .println ( "An Identifier can not be bound to more than one Expression!" ) ; //$NON-NLS-1$ System.err.println ( "Identifier: " + this ) ; //$NON-NLS-1$ System.err.println ( "Old boundToExpression: " + this.boundToExpression ) ; //$NON-NLS-1$ System.err.println ( "New boundToExpression: " + pBoundToExpression ) ; //$NON-NLS-1$ System.err.println ( "Old boundToIdentifier: " + this.boundToIdentifier ) ; //$NON-NLS-1$ System.err.println ( "New boundToIdentifier: " + pBoundToIdentifier ) ; //$NON-NLS-1$ } this.boundToExpression = pBoundToExpression ; this.boundToIdentifier = pBoundToIdentifier ; } /** * Sets the set of this {@link Identifier}. * * @param pSet The set to set. * @see #set * @see #getSet() */ public final void setSet ( Set pSet ) { this.set = pSet ; } /** * Returns <code>e</code> if <code>id</code> equals the name of the * identifier. Else the identifier itself is returned. * * @return <code>e</code> if <code>id</code> equals the name of the * identifier, else the identifier itself. */ @ Override public final Expression substitute ( Identifier pId , Expression pExpression ) { if ( pExpression.getIdentifierFreeNotOnlyVariable ( ) ) { throw new NotOnlyFreeVariableException ( ) ; } if ( pId.equals ( this ) ) { /* * We need to clone the expression here to make sure we can distinguish an * expression in the pretty printer that is substituted multiple times */ return pExpression.clone ( ) ; } return this ; } /** * {@inheritDoc} * * @see Expression#toLatexStringBuilder(LatexStringBuilderFactory,int) */ @ Override public final LatexStringBuilder toLatexStringBuilder ( LatexStringBuilderFactory pLatexStringBuilderFactory , int pIndent ) { LatexStringBuilder builder = pLatexStringBuilderFactory.newBuilder ( PRIO_IDENTIFIER , LATEX_IDENTIFIER , pIndent , this.toPrettyString ( ) .toString ( ) ) ; builder.addText ( "{" //$NON-NLS-1$ + this.name.replaceAll ( "_" , "\\\\_" ) + "}" ) ; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ return builder ; } /** * {@inheritDoc} * * @see Expression#toPrettyStringBuilder(PrettyStringBuilderFactory) */ @ Override public final PrettyStringBuilder toPrettyStringBuilder ( PrettyStringBuilderFactory pPrettyStringBuilderFactory ) { if ( this.prettyStringBuilder == null ) { this.prettyStringBuilder = pPrettyStringBuilderFactory.newBuilder ( this , PRIO_IDENTIFIER ) ; this.prettyStringBuilder.addIdentifier ( this.name ) ; } return this.prettyStringBuilder ; } }