RecursiveEvaluableExpressionVisitor.java
package de.uka.ipd.sdq.beagle.core.evaluableexpressions.util;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.AdditionExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.ComparisonExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.ConstantExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.DivisionExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableVariable;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.ExponentationExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.ExponentialFunctionExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.IfThenElseExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.LogarithmExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.MultiplicationExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.NaturalLogarithmExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.SineExpression;
import de.uka.ipd.sdq.beagle.core.evaluableexpressions.SubtractionExpression;
import org.apache.commons.lang3.Validate;
import java.util.Iterator;
/**
* Visitor of {@link EvaluableExpression EvaluableExpressions}, recursively visiting all
* their inner expressions.
*
* <p>This visitor will start at the expression passed to
* {@link #visitRecursively(EvaluableExpression)} and call the according {@code at} hook.
* Afterwards, it will recursively visit all inner expressions and then call the
* {@code after} hook. It thus realises a depth-first traversal of the tree formed by each
* expression. If {@link #stopTraversingInnerExpressions()} is called, the traversal will
* no longer visit inner expressions. Instead, it will go “up” the tree again, whilst
* calling the {@code after} hooks, until it reached the initial expression and then
* terminate. Given that no exception is thrown, the traversal of one expression tree that
* only contains pairwise different inner expressions has these properties:
*
* <ul>
*
* <li> for each type, the number of called {@code at} hooks will equal the number of
* called {@code after} hooks.
*
* <li> if for two expression {@code e1} and {@code e2}, {@code atExpression(e1)} was
* called before {@code atExpression(e2)} was, {@code afterExpression(e2)} will be called
* before {@code afterExpression(e1)} will be called.
*
* </ul>
*
* <p>Please note that evaluable expressions may often contain an instance of one
* evaluable expression multiple times. For every new visit, traversing of inner
* expressions will be enabled.
*
* <p>This visitor is not thread safe. It may only be used to traverse one expression at a
* time, meaning that its results are undefined if
* {@link #visitRecursively(EvaluableExpression)} is called when
* {@link #getTraversalDepth()} does not return {@code -1}. There is however no limitation
* on how many expression trees can be visited by an instance of this class.
*
* @author Joshua Gleitze
* @see ExpressionTreeWalker
*/
public abstract class RecursiveEvaluableExpressionVisitor extends PartialExpressionTreeWalker {
/**
* The visitor actually doing the recursive visiting.
*/
private final RecursiveWalker recursiveWalker = new RecursiveWalker();
/**
* How deeply we have the traversed so far. Will be 0 at the root.
*/
private int depth;
/**
* How many expressions we’ve seen so far. Will be 1 at the root.
*/
private int count;
/**
* Starts visiting {@code expression} recursively.
*
* @param expression The expression that forms the root of the tree this visitor shall
* traverse. Must not be {@code null}.
*/
protected void visitRecursively(final EvaluableExpression expression) {
Validate.notNull(expression, "Cannot visit null.");
this.startTraversingInnerExpressions();
this.depth = -1;
this.count = 0;
expression.receive(this.recursiveWalker);
}
/**
* Private hook called when starting to visit an expression.
*
* @param expression The momentary visited expression.
*/
private void atExpressionPrivate(final EvaluableExpression expression) {
this.depth++;
this.count++;
this.atExpression(expression);
}
/**
* Called when leaving any {@link EvaluableExpression}. Will be called after its inner
* expressions were visited and after the specific {@code after*} hook will was
* called.
*
* @param expression The momentary visited expression.
*/
private void afterExpressionPrivate(final EvaluableExpression expression) {
this.depth--;
}
@Override
protected int getVisitedCount() {
return this.count;
}
@Override
protected int getTraversalDepth() {
return this.depth;
}
/**
* The actual visitor passed to the expressions. Does the actual walking. Realised as
* private nested class to hide the {@code visit} methods from clients.
*
* @author Joshua Gleitze
*/
private class RecursiveWalker implements EvaluableExpressionVisitor {
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.AdditionExpression)
*/
@Override
public final void visit(final AdditionExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atAddition(expression);
final Iterator<EvaluableExpression> innerExpressions = expression.getSummands().iterator();
while (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()
&& innerExpressions.hasNext()) {
innerExpressions.next().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterAddition(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de
* .uka.ipd.sdq.beagle.core.evaluableexpressions.MultiplicationExpression)
*/
@Override
public final void visit(final MultiplicationExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atMultiplication(expression);
final Iterator<EvaluableExpression> innerExpressions = expression.getFactors().iterator();
while (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()
&& innerExpressions.hasNext()) {
innerExpressions.next().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterMultiplication(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableVariable)
*/
@Override
public final void visit(final EvaluableVariable variable) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(variable);
RecursiveEvaluableExpressionVisitor.this.atVariable(variable);
// no inner expressions to visit
RecursiveEvaluableExpressionVisitor.this.afterExpression(variable);
RecursiveEvaluableExpressionVisitor.this.afterVariable(variable);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(variable);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.ComparisonExpression)
*/
@Override
public final void visit(final ComparisonExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atComparison(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getSmaller().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getGreater().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterComparison(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.ConstantExpression)
*/
@Override
public final void visit(final ConstantExpression constant) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(constant);
RecursiveEvaluableExpressionVisitor.this.atConstant(constant);
// no inner expressions to visit
RecursiveEvaluableExpressionVisitor.this.afterExpression(constant);
RecursiveEvaluableExpressionVisitor.this.afterConstant(constant);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(constant);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.DivisionExpression)
*/
@Override
public final void visit(final DivisionExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atDivision(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getDividend().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getDivisor().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterDivision(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.ExponentationExpression)
*/
@Override
public final void visit(final ExponentationExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atExponentation(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getBase().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getExponent().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterExponentation(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de
* .uka.ipd.sdq.beagle.core.evaluableexpressions.ExponentialFunctionExpression)
*/
@Override
public final void visit(final ExponentialFunctionExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atExponentialFunction(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getExponent().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterExponentialFunction(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.IfThenElseExpression)
*/
@Override
public final void visit(final IfThenElseExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atIfThenElse(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getIfStatement().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getThenStatement().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getElseStatement().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterIfThenElse(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.LogarithmExpression)
*/
@Override
public final void visit(final LogarithmExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atLogarithm(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getBase().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getAntilogarithm().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterLogarithm(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de
* .uka.ipd.sdq.beagle.core.evaluableexpressions.NaturalLogarithmExpression)
*/
@Override
public final void visit(final NaturalLogarithmExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atNaturalLogarithm(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getAntilogarithm().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterNaturalLogarithm(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.SineExpression)
*/
@Override
public final void visit(final SineExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atSine(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getArgument().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterSine(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
/*
* (non-Javadoc)
*
* @see
* de.uka.ipd.sdq.beagle.core.evaluableexpressions.EvaluableExpressionVisitor#
* visit(de .uka.ipd.sdq.beagle.core.evaluableexpressions.SubstractionExpression)
*/
@Override
public final void visit(final SubtractionExpression expression) {
RecursiveEvaluableExpressionVisitor.this.atExpressionPrivate(expression);
RecursiveEvaluableExpressionVisitor.this.atSubtraction(expression);
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getMinuend().receive(this);
}
if (RecursiveEvaluableExpressionVisitor.this.willTraverseInnerExpressions()) {
expression.getSubtrahend().receive(this);
}
RecursiveEvaluableExpressionVisitor.this.afterExpression(expression);
RecursiveEvaluableExpressionVisitor.this.afterSubtraction(expression);
RecursiveEvaluableExpressionVisitor.this.afterExpressionPrivate(expression);
}
}
}