package de.unisiegen.tpml.core.expressions ; import java.text.MessageFormat ; import de.unisiegen.tpml.core.Messages ; import de.unisiegen.tpml.core.exceptions.LanguageParserMultiException ; import de.unisiegen.tpml.core.languages.LanguageParserException ; /** * Instances of this class represent projections in the expression hierarchy. * * @author Benedikt Meurer * @author Christian Fehler * @version $Rev:1053 $ * @see UnaryOperator */ public class Projection extends UnaryOperator { /** * The keyword <code>_</code>. */ private static final String UNDERLINE = "_" ; //$NON-NLS-1$ /** * The keyword <code>#</code>. */ private static final String HASHKEY = "#" ; //$NON-NLS-1$ /** * The caption of this {@link Expression}. */ private static final String CAPTION = Expression .getCaption ( Projection.class ) ; /** * The arity of the projection. * * @see #getArity() */ private int arity ; /** * The index of the projection. * * @see #getIndex() */ private int index ; /** * Allocates a new {@link Projection} with the given <code>arity</code> and * the <code>index</code> of the item that should be selected. * * @param pArity the arity of the tuple to which this projection can be * applied. * @param pIndex the index of the item to select from the tuple, starting with * <code>1</code>. * @throws IllegalArgumentException if the <code>arity</code> or the * <code>index</code> is invalid. */ public Projection ( int pArity , int pIndex ) { this ( pArity , pIndex , HASHKEY + pArity + UNDERLINE + pIndex ) ; } /** * Allocates a new {@link Projection} with the given <code>arity</code> and * the <code>index</code> of the item that should be selected. * * @param pArity the arity of the tuple to which this projection can be * applied. * @param pIndex the index of the item to select from the tuple, starting with * <code>1</code>. * @param pParserArityStartOffset The start offset of the arity in the source * code. * @param pParserArityEndOffset The end offset of the arity in the source * code. * @param pParserIndexStartOffset The start offset of the index in the source * code. * @param pParserIndexEndOffset The end offset of the index in the source * code. * @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. * @throws IllegalArgumentException if the <code>arity</code> or the * <code>index</code> is invalid. */ public Projection ( int pArity , int pIndex , int pParserArityStartOffset , int pParserArityEndOffset , int pParserIndexStartOffset , int pParserIndexEndOffset , int pParserStartOffset , int pParserEndOffset ) { this ( pArity , pIndex , HASHKEY + pArity + UNDERLINE + pIndex , pParserArityStartOffset , pParserArityEndOffset , pParserIndexStartOffset , pParserIndexEndOffset ) ; this.parserStartOffset = pParserStartOffset ; this.parserEndOffset = pParserEndOffset ; } /** * Allocates a new {@link Projection} with the given <code>arity</code> and * the <code>index</code> of the item that should be selected, and the * string representation <code>op</code>. * * @param pArity the arity of the tuple to which this projection can be * applied. * @param pIndex the index of the item to select from the tuple, starting with * <code>1</code>. * @param pOp the string representation of the projectin. * @throws IllegalArgumentException if the <code>arity</code> or the * <code>index</code> is invalid. */ protected Projection ( int pArity , int pIndex , String pOp ) { super ( pOp ) ; // validate the settings if ( pArity <= 0 ) { throw new IllegalArgumentException ( MessageFormat.format ( Messages .getString ( "Exception.2" ) , String.valueOf ( pArity ) ) ) ; //$NON-NLS-1$ } else if ( pIndex <= 0 ) { throw new IllegalArgumentException ( MessageFormat.format ( Messages .getString ( "Exception.3" ) , String.valueOf ( pIndex ) ) ) ; //$NON-NLS-1$ } else if ( pIndex > pArity ) { throw new IllegalArgumentException ( MessageFormat.format ( Messages .getString ( "Exception.4" ) , String.valueOf ( pIndex ) , String //$NON-NLS-1$ .valueOf ( pArity ) ) ) ; } this.arity = pArity ; this.index = pIndex ; } /** * Allocates a new {@link Projection} with the given <code>arity</code> and * the <code>index</code> of the item that should be selected, and the * string representation <code>op</code>. * * @param pArity the arity of the tuple to which this projection can be * applied. * @param pIndex the index of the item to select from the tuple, starting with * <code>1</code>. * @param pOp the string representation of the projectin. * @param pParserArityStartOffset The start offset of the arity in the source * code. * @param pParserArityEndOffset The end offset of the arity in the source * code. * @param pParserIndexStartOffset The start offset of the index in the source * code. * @param pParserIndexEndOffset The end offset of the index in the source * code. * @throws IllegalArgumentException if the <code>arity</code> or the * <code>index</code> is invalid. */ protected Projection ( int pArity , int pIndex , String pOp , int pParserArityStartOffset , int pParserArityEndOffset , int pParserIndexStartOffset , int pParserIndexEndOffset ) { super ( pOp ) ; // validate the settings if ( pArity <= 0 ) { throw new LanguageParserException ( MessageFormat.format ( Messages .getString ( "Exception.2" ) , String.valueOf ( pArity ) ) , //$NON-NLS-1$ pParserArityStartOffset , pParserArityEndOffset ) ; } else if ( pIndex <= 0 ) { throw new LanguageParserException ( MessageFormat.format ( Messages .getString ( "Exception.3" ) , String.valueOf ( pIndex ) ) , //$NON-NLS-1$ pParserIndexStartOffset , pParserIndexEndOffset ) ; } else if ( pIndex > pArity ) { throw new LanguageParserMultiException ( new String [ ] { MessageFormat.format ( Messages.getString ( "Exception.4" ) , String //$NON-NLS-1$ .valueOf ( pArity ) , String.valueOf ( pIndex ) ) , MessageFormat.format ( Messages.getString ( "Exception.5" ) , String //$NON-NLS-1$ .valueOf ( pIndex ) , String.valueOf ( pArity ) ) } , new int [ ] { pParserArityStartOffset , pParserIndexStartOffset } , new int [ ] { pParserArityEndOffset , pParserIndexEndOffset } ) ; } this.arity = pArity ; this.index = pIndex ; } /** * {@inheritDoc} * * @see UnaryOperator#applyTo(Expression) */ @ Override public Expression applyTo ( Expression pExpression ) throws UnaryOperatorException { try { Expression [ ] expressions = ( ( Tuple ) pExpression ).getExpressions ( ) ; if ( ! pExpression.isValue ( ) ) { throw new UnaryOperatorException ( this , pExpression ) ; } if ( this.arity != expressions.length ) { throw new UnaryOperatorException ( this , pExpression ) ; } return expressions [ this.index - 1 ] ; } catch ( ClassCastException cause ) { // cast of expression to tuple failed throw new UnaryOperatorException ( this , pExpression , cause ) ; } } /** * {@inheritDoc} * * @see Expression#clone() */ @ Override public Projection clone ( ) { return new Projection ( this.arity , this.index , getText ( ) ) ; } /** * Returns the arity. * * @return the arity. */ public int getArity ( ) { return this.arity ; } /** * {@inheritDoc} */ @ Override public String getCaption ( ) { return CAPTION ; } /** * Returns the index. * * @return the index. */ public int getIndex ( ) { return this.index ; } }