org.eclipse.ocl.utilities.AbstractVisitor Maven / Gradle / Ivy
/**
*
*
* Copyright (c) 2005, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* E.D. Willink - Fix NPE in visiting operation call with null source
*
*
*
* $Id: AbstractVisitor.java,v 1.7 2008/04/27 23:16:03 cdamus Exp $
*/
package org.eclipse.ocl.utilities;
import java.util.Collections;
import java.util.List;
import org.eclipse.ocl.expressions.AssociationClassCallExp;
import org.eclipse.ocl.expressions.BooleanLiteralExp;
import org.eclipse.ocl.expressions.CollectionItem;
import org.eclipse.ocl.expressions.CollectionLiteralExp;
import org.eclipse.ocl.expressions.CollectionLiteralPart;
import org.eclipse.ocl.expressions.CollectionRange;
import org.eclipse.ocl.expressions.EnumLiteralExp;
import org.eclipse.ocl.expressions.IfExp;
import org.eclipse.ocl.expressions.IntegerLiteralExp;
import org.eclipse.ocl.expressions.InvalidLiteralExp;
import org.eclipse.ocl.expressions.IterateExp;
import org.eclipse.ocl.expressions.IteratorExp;
import org.eclipse.ocl.expressions.LetExp;
import org.eclipse.ocl.expressions.MessageExp;
import org.eclipse.ocl.expressions.NullLiteralExp;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.expressions.OperationCallExp;
import org.eclipse.ocl.expressions.PropertyCallExp;
import org.eclipse.ocl.expressions.RealLiteralExp;
import org.eclipse.ocl.expressions.StateExp;
import org.eclipse.ocl.expressions.StringLiteralExp;
import org.eclipse.ocl.expressions.TupleLiteralExp;
import org.eclipse.ocl.expressions.TupleLiteralPart;
import org.eclipse.ocl.expressions.TypeExp;
import org.eclipse.ocl.expressions.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.expressions.UnspecifiedValueExp;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.expressions.VariableExp;
/**
*
* An abstract implementation of the {@link Visitor} API, in which subclasses
* need only selectively override handleXxx(...)
methods for
* internal AST nodes and visitXxx(...)
methods for leaf nodes.
*
* The {@link #result} value is convenient for accumulating the result of the
* visitation. In the subclass, simply assign/modify the result value as
* necessary in the overridden visitation methods, and this framework will
* ensure that it is returned as the overall value of the
* {@link Visitable#accept(Visitor)} call.
*
*
* @author Christian W. Damus (cdamus)
*/
public abstract class AbstractVisitor
implements Visitor {
/**
* Accumulator for the result of the AST visitation.
*/
protected T result;
/**
* Initializes me.
*/
protected AbstractVisitor() {
super();
}
/**
* Initializes me with an initial value for my result.
*
* @param initialValue my initial result value
*/
protected AbstractVisitor(T initialValue) {
this.result = initialValue;
}
/**
* A null-safe visitation of the specified visitable.
*
* @param v a visitable, or null
* @return null
if the visitable is null
;
* otherwise, the result of visiting it
*
* @since 1.2
*/
protected T safeVisit(Visitable v) {
return (v == null)? null : v.accept(this);
}
/**
* Visits the operation-call source and then its arguments.
* Returns the result of {@link #handleOperationCallExp(OperationCallExp, Object, List)}.
*/
public T visitOperationCallExp(OperationCallExp callExp) {
OCLExpression source = callExp.getSource();
T sourceResult = safeVisit(source);
List argumentResults;
List> arguments = callExp.getArgument();
if (arguments.isEmpty()) {
argumentResults = Collections.emptyList();
} else {
argumentResults = new java.util.ArrayList(arguments.size());
for (OCLExpression qual : arguments) {
argumentResults.add(safeVisit(qual));
}
}
return handleOperationCallExp(callExp, sourceResult, argumentResults);
}
/**
* Visits the specified operation call with the results of visiting
* its source and arguments (if any).
*
* @param callExp the operation call expression
* @param sourceResult the result of visiting the expression's source
* @param argumentResults the results of visiting the expression's
* arguments, or an empty list if there are no arguments
*
* @return the accumulated {@link #result}, by default
*
* @see #visitOperationCallExp(OperationCallExp)
*/
protected T handleOperationCallExp(OperationCallExp callExp,
T sourceResult, List argumentResults) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitVariableExp(VariableExp v) {
return result;
}
/**
* Visits the property-call source and then its qualifiers (if any).
* Returns the result of {@link #handlePropertyCallExp(PropertyCallExp, Object, List)}.
*/
public T visitPropertyCallExp(PropertyCallExp callExp) {
// source is null when the property call expression is an
// association class navigation qualifier
T sourceResult = safeVisit(callExp.getSource());
List qualifierResults;
List> qualifiers = callExp.getQualifier();
if (qualifiers.isEmpty()) {
qualifierResults = Collections.emptyList();
} else {
qualifierResults = new java.util.ArrayList(qualifiers.size());
for (OCLExpression qual : qualifiers) {
qualifierResults.add(safeVisit(qual));
}
}
return handlePropertyCallExp(callExp, sourceResult, qualifierResults);
}
/**
* Visits the specified property call with the results of visiting
* its source and qualifiers (if any). Note that in the case of a property
* call expression as a qualifier of an association class call, the
* property call does not have a source and, therefore, the
* sourceResult will be null
in that case.
*
* @param callExp the property call expression, if there is a source
* @param sourceResult the result of visiting the expression's source
* @param qualifierResults the results of visiting the expression's
* qualifiers, or an empty list if there are no qualifiers
*
* @return the accumulated {@link #result}, by default
*
* @see #visitPropertyCallExp(PropertyCallExp)
*/
protected T handlePropertyCallExp(PropertyCallExp callExp,
T sourceResult, List qualifierResults) {
return result;
}
/**
* Visits the association-class-call source and then its qualifiers (if any).
* Returns the result of {@link #handleAssociationClassCallExp(AssociationClassCallExp, Object, List)}.
*/
public T visitAssociationClassCallExp(AssociationClassCallExp callExp) {
T sourceResult = safeVisit(callExp.getSource());
List qualifierResults;
List> qualifiers = callExp.getQualifier();
if (qualifiers.isEmpty()) {
qualifierResults = Collections.emptyList();
} else {
qualifierResults = new java.util.ArrayList(qualifiers.size());
for (OCLExpression qual : qualifiers) {
qualifierResults.add(safeVisit(qual));
}
}
return handleAssociationClassCallExp(callExp, sourceResult, qualifierResults);
}
/**
* Visits the specified association-class call with the results of visiting
* its source and qualifiers (if any).
*
* @param callExp the association-class call expression
* @param sourceResult the result of visiting the expression's source
* @param qualifierResults the results of visiting the expression's
* qualifiers, or an empty list if there are no qualifiers
*
* @return the accumulated {@link #result}, by default
*
* @see #visitAssociationClassCallExp(AssociationClassCallExp)
*/
protected T handleAssociationClassCallExp(AssociationClassCallExp callExp,
T sourceResult, List qualifierResults) {
return result;
}
/**
* Visits the variable's initialization expression (if any).
* Returns the result of {@link #handleVariable(Variable, Object)}.
*/
public T visitVariable(Variable variable) {
T initResult = safeVisit(variable.getInitExpression());
return handleVariable(variable, initResult);
}
/**
* Visits the specified variable with the results of visiting
* its initializer (if any).
*
* @param variable the variable
* @param initResult the result of visiting the expression's initializer,
* or null
if it has none
*
* @return the accumulated {@link #result}, by default
*
* @see #visitVariable(Variable)
*/
protected T handleVariable(Variable variable,
T initResult) {
return result;
}
/**
* Visits the if expression's condition, then, and else expressions.
* Returns the result of {@link #handleIfExp(IfExp, Object, Object, Object)}.
*/
public T visitIfExp(IfExp ifExp) {
return handleIfExp(ifExp,
safeVisit(ifExp.getCondition()),
safeVisit(ifExp.getThenExpression()),
safeVisit(ifExp.getElseExpression()));
}
/**
* Visits the specified if expression with the results of visiting
* its condition, then, and else expressions.
*
* @param ifExp the if expression
* @param conditionResult the result of visiting the expression's condition
* @param thenResult the result of visiting the expression's then
* @param elseResult the result of visiting the expression's else
*
* @return the accumulated {@link #result}, by default
*
* @see #visitIfExp(IfExp)
*/
protected T handleIfExp(IfExp ifExp, T conditionResult, T thenResult,
T elseResult) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitTypeExp(TypeExp t) {
return result;
}
/**
* Visits the message expression's target and then its arguments.
* Returns the result of {@link #handleMessageExp(MessageExp, Object, List)}.
*/
public T visitMessageExp(MessageExp messageExp) {
T targetResult = safeVisit(messageExp.getTarget());
List argumentResults;
List> arguments = messageExp.getArgument();
if (arguments.isEmpty()) {
argumentResults = Collections.emptyList();
} else {
argumentResults = new java.util.ArrayList(arguments.size());
for (OCLExpression qual : arguments) {
argumentResults.add(safeVisit(qual));
}
}
return handleMessageExp(messageExp, targetResult, argumentResults);
}
/**
* Visits the specified message expression with the results of visiting
* its target and arguments (if any).
*
* @param messageExp the message expression
* @param targetResult the result of visiting the expression's target
* @param argumentResults the results of visiting the expression's
* arguments, or an empty list if there are no arguments
*
* @return the accumulated {@link #result}, by default
*
* @see #visitMessageExp(MessageExp)
*/
protected T handleMessageExp(MessageExp messageExp,
T targetResult, List argumentResults) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitUnspecifiedValueExp(UnspecifiedValueExp unspecExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitStateExp(StateExp stateExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitIntegerLiteralExp(IntegerLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitUnlimitedNaturalLiteralExp(UnlimitedNaturalLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitRealLiteralExp(RealLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitStringLiteralExp(StringLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitBooleanLiteralExp(BooleanLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitNullLiteralExp(NullLiteralExp literalExp) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitInvalidLiteralExp(InvalidLiteralExp literalExp) {
return result;
}
/**
* Visits the tuple literal's parts.
* Returns the result of {@link #handleTupleLiteralExp(TupleLiteralExp, List)}.
*/
public T visitTupleLiteralExp(TupleLiteralExp literalExp) {
List partResults;
List> parts = literalExp.getPart();
if (parts.isEmpty()) {
partResults = Collections.emptyList();
} else {
partResults = new java.util.ArrayList(parts.size());
for (TupleLiteralPart part : parts) {
partResults.add(safeVisit(part));
}
}
return handleTupleLiteralExp(literalExp, partResults);
}
/**
* Visits the specified tuple literal expression with the results of visiting
* its parts (if any).
*
* @param literalExp the tuple literal expression
* @param partResults the results of visiting the expression's
* parts, or an empty list if there are no parts
*
* @return the accumulated {@link #result}, by default
*
* @see #visitTupleLiteralExp(TupleLiteralExp)
*/
protected T handleTupleLiteralExp(TupleLiteralExp literalExp,
List partResults) {
return result;
}
/**
* Visits the tuple literal part's value, if any.
* Returns the result of {@link #handleTupleLiteralPart(TupleLiteralPart, Object)}.
*/
public T visitTupleLiteralPart(TupleLiteralPart part) {
T valueResult = safeVisit(part.getValue());
return handleTupleLiteralPart(part, valueResult);
}
/**
* Visits the specified tuple literal part with the results of visiting
* its value (if any).
*
* @param part the tuple literal part
* @param valueResult the result of visiting the expression's value, or
* null
if it has no value
*
* @return the accumulated {@link #result}, by default
*
* @see #visitTupleLiteralPart(TupleLiteralPart)
*/
protected T handleTupleLiteralPart(TupleLiteralPart part,
T valueResult) {
return result;
}
/**
* Visits the let's variable declaration then its 'in' expression.
* Returns the result of {@link #handleLetExp(LetExp, Object, Object)}.
*/
public T visitLetExp(LetExp letExp) {
return handleLetExp(letExp,
safeVisit(letExp.getVariable()),
safeVisit(letExp.getIn()));
}
/**
* Visits the specified let expression with the results of visiting
* its variable and in expression.
*
* @param letExp the let expression
* @param variableResult the result of visiting the expression's variable
* @param inResult the result of visiting the expression's in expression
*
* @return the accumulated {@link #result}, by default
*
* @see #visitLetExp(LetExp)
*/
protected T handleLetExp(LetExp letExp, T variableResult, T inResult) {
return result;
}
/**
* Simply returns {@link #result}.
*/
public T visitEnumLiteralExp(EnumLiteralExp literalExp) {
return result;
}
/**
* Visits the collection literal's parts.
*
* Returns the result of {@link #handleCollectionLiteralExp(CollectionLiteralExp, List)}.
*/
public T visitCollectionLiteralExp(CollectionLiteralExp literalExp) {
List partResults;
List> parts = literalExp.getPart();
if (parts.isEmpty()) {
partResults = Collections.emptyList();
} else {
partResults = new java.util.ArrayList(parts.size());
for (CollectionLiteralPart part : parts) {
partResults.add(safeVisit(part));
}
}
return handleCollectionLiteralExp(literalExp, partResults);
}
/**
* Visits the specified collection literal expression with the results of visiting
* its parts (if any).
*
* @param literalExp the collection literal expression
* @param partResults the results of visiting the expression's
* parts, or an empty list if there are no parts
*
* @return the accumulated {@link #result}, by default
*
* @see #visitCollectionLiteralExp(CollectionLiteralExp)
*/
protected T handleCollectionLiteralExp(CollectionLiteralExp literalExp,
List partResults) {
return result;
}
/**
* Visits the item's item expression.
*
* Returns the result of {@link #handleCollectionItem(CollectionItem, Object)}
*/
public T visitCollectionItem(CollectionItem item) {
T itemResult = safeVisit(item.getItem());
return handleCollectionItem(item, itemResult);
}
/**
* Visits the specified collection item with the result of visiting
* its item expression.
*
* @param item the collection item
* @param itemResult the result of visiting the item's item expression
*
* @return the accumulated {@link #result}, by default
*
* @see #visitCollectionItem(CollectionItem)
*/
protected T handleCollectionItem(CollectionItem item, T itemResult) {
return result;
}
/**
* Visits the range's first and last expressions.
*
* Returns the result of {@link #handleCollectionRange(CollectionRange, Object, Object)}.
*/
public T visitCollectionRange(CollectionRange range) {
return handleCollectionRange(range,
safeVisit(range.getFirst()),
safeVisit(range.getLast()));
}
/**
* Visits the specified collection range with the results of visiting
* its first and last expressions.
*
* @param range the collection range
* @param firstResult the result of visiting the range's first expression
* @param lastResult the result of visiting the range's last expression
*
* @return the accumulated {@link #result}, by default
*
* @see #visitCollectionRange(CollectionRange)
*/
protected T handleCollectionRange(CollectionRange range, T firstResult,
T lastResult) {
return result;
}
/**
* Visits the iterator's source, then its variables, followed by its body
* expression.
* Returns the result of {@link #handleIteratorExp(IteratorExp, Object, List, Object)}.
*/
public T visitIteratorExp(IteratorExp callExp) {
T sourceResult = safeVisit(callExp.getSource());
List variableResults;
List> variables = callExp.getIterator();
if (variables.isEmpty()) {
variableResults = Collections.emptyList();
} else {
variableResults = new java.util.ArrayList(variables.size());
for (Variable iterVar : variables) {
variableResults.add(safeVisit(iterVar));
}
}
T bodyResult = safeVisit(callExp.getBody());
return handleIteratorExp(callExp, sourceResult, variableResults, bodyResult);
}
/**
* Visits the specified iterator expression with the results of visiting
* its source, its iterator variables, and its body expression.
*
* @param callExp the iterator expression
* @param sourceResult the result of visiting the expression's source
* @param variableResults the results of visiting the expression's
* iterator variables
* @param bodyResult the result of visiting the expression's body
*
* @return the accumulated {@link #result}, by default
*
* @see #visitIteratorExp(IteratorExp)
*/
protected T handleIteratorExp(IteratorExp callExp,
T sourceResult, List variableResults, T bodyResult) {
return result;
}
/**
* Visits the iterate's source, then its iterator variables,
* result variable, and body expression.
* Returns the result of {@link #handleIterateExp(IterateExp, Object, List, Object, Object)}.
*/
public T visitIterateExp(IterateExp callExp) {
T sourceResult = safeVisit(callExp.getSource());
List variableResults;
List> variables = callExp.getIterator();
if (variables.isEmpty()) {
variableResults = Collections.emptyList();
} else {
variableResults = new java.util.ArrayList(variables.size());
for (Variable iterVar : variables) {
variableResults.add(safeVisit(iterVar));
}
}
T resultResult = safeVisit(callExp.getResult());
T bodyResult = safeVisit(callExp.getBody());
return handleIterateExp(callExp, sourceResult, variableResults,
resultResult, bodyResult);
}
/**
* Visits the specified iterate expression with the results of visiting
* its source, its iterator variables, its result variable, and its body
* expression.
*
* @param callExp the iterate expression
* @param sourceResult the result of visiting the expression's source
* @param variableResults the results of visiting the expression's
* iterator variables
* @param resultResult the result of visiting the expressions' result variable
* @param bodyResult the result of visiting the expression's body
*
* @return the accumulated {@link #result}, by default
*
* @see #visitIterateExp(IterateExp)
*/
protected T handleIterateExp(IterateExp callExp,
T sourceResult, List variableResults, T resultResult, T bodyResult) {
return result;
}
/**
* Visits the expressions context variable, its parameter variables (if any),
* its result variable (if any), and finally its body expression.
*
* Returns the result of
* {@link #handleExpressionInOCL(ExpressionInOCL, Object, Object, List, Object)}.
*/
public T visitExpressionInOCL(ExpressionInOCL expression) {
T contextResult = safeVisit(expression.getContextVariable());
Variable resultVar = expression.getResultVariable();
T resultResult = safeVisit(resultVar);
List parameterResults;
List> parameters = expression.getParameterVariable();
if (parameters.isEmpty()) {
parameterResults = Collections.emptyList();
} else {
parameterResults = new java.util.ArrayList(parameters.size());
for (Variable iterVar : parameters) {
parameterResults.add(safeVisit(iterVar));
}
}
T bodyResult = safeVisit(expression.getBodyExpression());
return handleExpressionInOCL(expression, contextResult, resultResult,
parameterResults, bodyResult);
}
/**
* Visits the specified expression-in-OCL with the results of visiting
* its context variable, its result variable (if any), its parameter
* variables (if any), and its body expression.
*
* @param expression the expression-in-OCL
* @param contextResult the result of visiting the expression's context variable
* @param resultResult the result of visiting the expressions' result variable,
* or null
if there is no result variable
* @param parameterResults the results of visiting the expression's
* parameter variables, or an empty list if there are none
* @param bodyResult the result of visiting the expression's body
*
* @return the accumulated {@link #result}, by default
*
* @see #visitExpressionInOCL(ExpressionInOCL)
*/
protected T handleExpressionInOCL(ExpressionInOCL expression,
T contextResult, T resultResult, List parameterResults, T bodyResult) {
return result;
}
/**
* Visits the constraint's specification, if any (and if the
* {@link #getSpecification(Object)} method is overridden).
*
* Returns the result of {@link #handleConstraint(Object, Object)}.
*
* @see #getSpecification(Object)
*/
public T visitConstraint(CT constraint) {
T specificationResult = safeVisit(getSpecification(constraint));
return handleConstraint(constraint, specificationResult);
}
/**
* Visits the specified constraint with the results of visiting
* its specification.
*
* @param constraint the constraint
* @param specificationResult the result of visiting the constraint's
* specification, or null
if either it has none or the
* {@link #getSpecification(Object)} method is not overridden
*
* @return the accumulated {@link #result}, by default
*
* #see {@link #getSpecification(Object)}
* @see #visitConstraint(Object)
*/
protected T handleConstraint(CT constraint, T specificationResult) {
return result;
}
/**
* Overridden by subclasses interested in visiting constraints, to get the
* constraint's specification.
*
* @param constraint a constraint
* @return its specification
*
* @see #visitConstraint(Object)
*/
protected ExpressionInOCL getSpecification(CT constraint) {
return null;
}
} //VisitorImpl