/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* JavaBlockStatement.java
* Creation date: Sep 11, 2003.
* By: Edward Lam
*/
package org.openquark.cal.internal.javamodel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
import org.openquark.cal.internal.javamodel.JavaExpression.JavaField;
import org.openquark.cal.internal.javamodel.JavaExpression.LocalVariable;
import org.openquark.cal.internal.javamodel.JavaExpression.MethodInvocation;
import org.openquark.cal.services.Assert;
/**
* Java object representation for BlockStatements.
* In the Java grammar, this represents a BlockStatement, which represents LocalVariableDeclarations, and so-called Statements.
* @author Edward Lam
*/
public abstract class JavaStatement {
/**
* A private constructor to prevent subclasses other than the inner classes above.
*/
private JavaStatement() {
// Constructor made private to prevent instantiation.
}
/**
* @return representation of this JavaStatement for debug purposes only.
*/
@Override
public String toString() {
return JavaSourceGenerator.toDebugString(this);
}
/**
* @return true if the statement is the empty block {}.
*/
boolean emptyStatement() {
return false;
}
/**
* Accepts the visitation of a visitor, which implements the
* JavaModelVisitor interface. This abstract method is to be overriden
* by each concrete subclass so that the corrent visit method on the
* visitor may be called based upon the type of the element being
* visited. Each concrete subclass of JavaStatement should correspond
* one-to-one with a visit method declaration in the SourceModelVisitor
* interface.
* <p>
*
* As the JavaModelVisitor follows a more general visitor pattern
* where arguments can be passed into the visit methods and return
* values obtained from them, this method passes through the argument
* into the visit method, and returns as its return value the return
* value of the visit method.
* <p>
*
* Nonetheless, for a significant portion of the common cases, the state of the
* visitation can simply be kept as member variables within the visitor itself,
* thereby eliminating the need to use the argument and return value of the
* visit methods. In these scenarios, the recommended approach is to use
* {@link Void} as the type argument for both <code>T</code> and <code>R</code>, and
* pass in null as the argument, and return null as the return value.
* <p>
*
* @see JavaModelVisitor
*
* @param <T> the argument type. If the visitation argument is not used, specify {@link Void}.
* @param <R> the return type. If the return value is not used, specify {@link Void}.
*
* @param visitor
* the visitor
* @param arg
* the argument to be passed to the visitor's visitXXX method
* @return the return value of the visitor's visitXXX method
*/
public abstract <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg);
/**
* Encapsulates a number of block statements, optionally encapsulated by a try/catch block.
* @author Edward Lam
*/
public static final class Block extends JavaStatement {
/** the list of statements in this block. */
private final List<JavaStatement> blockStatements = new ArrayList<JavaStatement>();
/** The exception handlers for an enclosing try/catch block. */
private final List<JavaExceptionHandler> exceptionHandlers;
/** The number of local variable declarations in this block. */
private int nLocalVariableDeclarations = 0;
/**
* Constructor for a Block.
*/
public Block() {
this(Collections.<JavaExceptionHandler>emptyList());
}
/**
* Constructor for a Block
* @param exceptionHandlers any exception handlers for an enclosing try/catch block.
*/
public Block(List<JavaExceptionHandler> exceptionHandlers) {
Assert.isNotNull(exceptionHandlers);
this.exceptionHandlers = exceptionHandlers;
}
/**
* Add a statement to this block.
* @param blockStatement the statement to add.
* If the statement is a block, all component statements will be added separately.
*/
public void addStatement(JavaStatement blockStatement) {
assert (blockStatement != null) : "Attempt to add a null block statement.";
blockStatements.add(blockStatement);
if (blockStatement instanceof LocalVariableDeclaration) {
nLocalVariableDeclarations++;
}
}
/**
* Get the number of statements in this block.
* @return the number of statements.
*/
public int getNBlockStatements() {
return blockStatements.size();
}
/**
* Get the nth statement in this block.
* @param n the index of the statement to return.
* @return the nth statement in this block.
*/
public JavaStatement getNthBlockStatement(int n) {
return blockStatements.get(n);
}
/**
* Get the exception handlers for this block.
* @return the exception handlers for this block. Never null.
*/
public List<JavaExceptionHandler> getExceptionHandlers() {
if (exceptionHandlers.isEmpty()) {
return Collections.<JavaExceptionHandler>emptyList();
}
return new ArrayList<JavaExceptionHandler>(exceptionHandlers);
}
/**
* Get a copy of this block.
* @return Block a copy of this block.
*/
public Block getCopy() {
Block copy = new Block(getExceptionHandlers());
copy.blockStatements.addAll(blockStatements);
copy.nLocalVariableDeclarations = nLocalVariableDeclarations;
return copy;
}
/**
* @return true if the statement is the empty block {}.
*/
@Override
public boolean emptyStatement() {
return getNBlockStatements() == 0;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitBlockStatement(this, arg);
}
}
/**
* A Java expression that's been turned into a statement.
* @author Edward Lam
*/
public static final class ExpressionStatement extends JavaStatement {
/** The component expression. */
private final JavaExpression javaExpression;
/**
* Constructor for an expression statement.
* @param javaExpression
*/
public ExpressionStatement(JavaExpression javaExpression) {
Assert.isNotNull(javaExpression);
this.javaExpression = javaExpression;
}
/**
* Get the component expression.
* @return JavaExpression
*/
public JavaExpression getJavaExpression() {
if (javaExpression instanceof JavaExpression.PlaceHolder) {
return ((JavaExpression.PlaceHolder)javaExpression).getActualExpression();
}
return javaExpression;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitExpressionStatement(this, arg);
}
}
/**
* A local variable declaration.
* Note: array variables not supported here.
* @author Edward Lam
*/
public static final class LocalVariableDeclaration extends JavaStatement {
private final boolean isFinal;
/** The local variable. */
private final LocalVariable localVariable;
/** The initializer for the local variable declaration, or null if there isn't any. */
private final JavaExpression initializer;
/**
* Constructor for a LocalVariableDeclaration.
* @param localVariable the local variable
*/
public LocalVariableDeclaration(LocalVariable localVariable) {
this(localVariable, null);
}
/**
* Constructor for a LocalVariableDeclaration.
* @param localVariable the local variable
* @param initializer the initializer for the local variable
*/
public LocalVariableDeclaration(LocalVariable localVariable, JavaExpression initializer) {
this(localVariable, initializer, false);
}
/**
* Constructor for a LocalVariableDeclaration.
* @param localVariable the local variable
* @param initializer the initializer for the local variable
* @param isFinal whether the local variable is final or not
*/
public LocalVariableDeclaration(LocalVariable localVariable, JavaExpression initializer, boolean isFinal) {
Assert.isNotNull(localVariable);
this.localVariable = localVariable;
this.initializer = initializer;
this.isFinal = isFinal;
}
/**
* Get the local variable.
* @return LocalVariable
*/
public LocalVariable getLocalVariable() {
return localVariable;
}
/**
* Get the initializer for the local variable.
* @return JavaExpression the initializer, or null if there is no initializer.
*/
public JavaExpression getInitializer() {
return initializer;
}
/**
* @return boolean
*/
public boolean isFinal() {
return isFinal;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitLocalVariableDeclarationStatement(this, arg);
}
}
/**
* Models the java assert statement in both its 1 argument and 2 argument forms:
*
* assert conditionExpr;
* assert conditionExpr : onFailureExpr;
*
* @author Bo Ilic
*/
public static final class AssertStatement extends JavaStatement {
/**
* if conditionExpr, which must have type boolean, evaluates to false then the assertion throws
* a java.lang.AssertionError. Cannot be null.
*/
private final JavaExpression conditionExpr;
/**
* onFailureExpr is an expression having type != void. It is evaluated and then passed as an argument to
* AssertionError if the assertion fails. May be null, which indicates to call the no argument AssertionError
* on failure.
*/
private final JavaExpression onFailureExpr;
/**
* The type of the onFailureExpr. Cannot be void. This is used to invoke the correct version
* of the AssertionError constructor.
*/
private final JavaTypeName onFailureExprType;
/**
* @param booleanExpr the expression to assert is true.
*/
public AssertStatement(JavaExpression booleanExpr) {
this (booleanExpr, null, null);
}
/**
* @param conditionExpr - the expression to assert is true
* @param onFailureExpr - the expression used as an argument to the AssertionError constructor
* @param onFailureExprType - the type of onFailureExpr
*/
public AssertStatement(JavaExpression conditionExpr, JavaExpression onFailureExpr, JavaTypeName onFailureExprType) {
if (conditionExpr == null) {
throw new NullPointerException("conditionExpr cannot be null");
}
if ((onFailureExpr == null) != (onFailureExprType == null)) {
throw new NullPointerException("onFailureExpr and onFailureExprType must both be null or both be non-null");
}
if (onFailureExprType != null && onFailureExprType.equals(JavaTypeName.VOID)) {
throw new NullPointerException("onFailureExprType cannot be void");
}
this.conditionExpr = conditionExpr;
this.onFailureExpr = onFailureExpr;
this.onFailureExprType = onFailureExprType;
}
/**
* @return if conditionExpr, which must have type boolean, evaluates to false then the assertion throws
* a java.lang.AssertionError. Cannot be null.
*/
public JavaExpression getConditionExpr() {
return conditionExpr;
}
/**
* @return onFailureExpr is an expression having type != void. It is evaluated and then passed as an argument to
* AssertionError if the assertion fails. May be null, which indicates to call the no argument AssertionError
* on failure.
*/
public JavaExpression getOnFailureExpr() {
return onFailureExpr;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitAssertStatement(this, arg);
}
public JavaTypeName getOnFailureExprType() {
return onFailureExprType;
}
}
/**
* An If-Then-Else statement
* @author Edward Lam
*/
public static final class IfThenElseStatement extends JavaStatement {
/** The "if" condition. */
private final JavaExpression condition;
/** The "then" clause. */
private final JavaStatement thenStatement;
/** The "else" clause. */
private final JavaStatement elseStatement;
/**
* Constructor for an IfThenElseStatement, where there is only a "then" statement.
* @param condition the condition tested by the "if".
* @param thenStatement the statement for the "then" clause.
*/
public IfThenElseStatement(JavaExpression condition, JavaStatement thenStatement) {
this(condition, thenStatement, new Block());
}
/**
* Constructor for an IfThenElseStatement.
* @param condition the condition tested by the "if".
* @param thenStatement the statement for the "then" clause.
* @param elseStatement the statement for the "else" clause.
*/
public IfThenElseStatement(JavaExpression condition, JavaStatement thenStatement, JavaStatement elseStatement) {
Assert.isNotNull(condition);
Assert.isNotNull(thenStatement);
Assert.isNotNull(elseStatement);
this.condition = condition;
this.thenStatement = thenStatement;
this.elseStatement = elseStatement;
}
/**
* Get the "if" condition.
* @return JavaExpression
*/
public JavaExpression getCondition() {
return condition;
}
/**
* Get the "then" clause.
* @return JavaStatement
*/
public JavaStatement getThenStatement() {
return thenStatement;
}
/**
* Get the "else" clause.
* @return JavaStatement
*/
public JavaStatement getElseStatement() {
return elseStatement;
}
/**
* @return boolean true if the if-then-else has an empty else statement i.e. it is just "else {}", or equivalently, it is
* really an "if-then" statement without an else clause.
*/
public boolean hasEmptyElseStatement() {
return elseStatement.emptyStatement();
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitIfThenElseStatement(this, arg);
}
}
/**
* A switch statement.
* Note: Java supports multiple case labels for a given switch block statement group.
* @author Edward Lam
*/
public static final class SwitchStatement extends JavaStatement {
/** The condition tested by the switch. */
private final JavaExpression condition;
/** (IntCaseGroup) All cases except the default case, in added order. */
private List<IntCaseGroup> caseList = new ArrayList<IntCaseGroup>();
/** The default case. */
private DefaultCase defaultCase = null;
/**
* Constructor for a SwitchStatement.
* @param condition the condition tested by the switch.
*/
public SwitchStatement(JavaExpression condition) {
Assert.isNotNull(condition);
this.condition = condition;
}
/**
* Add a case to this switch statement.
* @param caseToAdd the case to add.
*/
public void addCase(SwitchCase caseToAdd) {
if (caseToAdd instanceof IntCaseGroup) {
caseList.add((IntCaseGroup)caseToAdd);
Collections.sort(caseList, new IntCaseGroupComparator());
} else if (caseToAdd instanceof DefaultCase) {
this.defaultCase = (DefaultCase)caseToAdd;
} else {
assert false : ("Unrecognized case type: " + caseToAdd.getClass().getName());
}
}
/**
* Get the condition tested by the switch.
* @return JavaExpression
*/
public JavaExpression getCondition() {
return condition;
}
/**
* Get the list of switch case groups (not including the default).
* @return List (IntCaseGroup)
*/
public List<IntCaseGroup> getCaseGroups () {
return new ArrayList<IntCaseGroup>(caseList);
}
/**
* Get the statement for the default case.
* @return JavaStatement
*/
public JavaStatement getDefaultStatement() {
if (defaultCase == null) {
return null;
}
return defaultCase.getStatement();
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitSwitchStatement(this, arg);
}
/**
* A switch case.
* @author Edward Lam
*/
public abstract static class SwitchCase {
/** The statements for this case. */
private final JavaStatement caseStatement;
/**
* Constructor for a SwitchCase.
* @param caseStatement the statements for this case.
*/
private SwitchCase(JavaStatement caseStatement) {
Assert.isNotNull(caseStatement);
this.caseStatement = caseStatement;
}
/**
* Get the statements for this case.
* @return JavaStatement
*/
public JavaStatement getStatement() {
return caseStatement;
}
/**
* Accepts the visitation of a visitor, which implements the
* JavaModelVisitor interface. This abstract method is to be overriden
* by each concrete subclass so that the corrent visit method on the
* visitor may be called based upon the type of the element being
* visited. Each concrete subclass of JavaStatement should correspond
* one-to-one with a visit method declaration in the SourceModelVisitor
* interface.
* <p>
*
* As the JavaModelVisitor follows a more general visitor pattern
* where arguments can be passed into the visit methods and return
* values obtained from them, this method passes through the argument
* into the visit method, and returns as its return value the return
* value of the visit method.
* <p>
*
* Nonetheless, for a significant portion of the common cases, the state of the
* visitation can simply be kept as member variables within the visitor itself,
* thereby eliminating the need to use the argument and return value of the
* visit methods. In these scenarios, the recommended approach is to use
* {@link Void} as the type argument for both <code>T</code> and <code>R</code>, and
* pass in null as the argument, and return null as the return value.
* <p>
*
* @see JavaModelVisitor
*
* @param <T> the argument type. If the visitation argument is not used, specify {@link Void}.
* @param <R> the return type. If the return value is not used, specify {@link Void}.
*
* @param visitor
* the visitor
* @param arg
* the argument to be passed to the visitor's visitXXX method
* @return the return value of the visitor's visitXXX method
*/
public abstract <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg);
}
private static class IntCaseGroupComparator implements Comparator<IntCaseGroup> {
public int compare (IntCaseGroup o1, IntCaseGroup o2) {
int i1 = o1.getNthCaseLabel(0);
int i2 = o2.getNthCaseLabel(0);
return i1 - i2;
}
}
/**
* A group of int cases with a common case statement.
* @author Edward Lam
*/
public static final class IntCaseGroup extends SwitchCase {
/** The case labels. */
private final int[] caseLabels;
/**
* Constructor for an IntCaseGroup with only one case label.
* @param caseLabel the case label
* @param caseStatement
*/
public IntCaseGroup(int caseLabel, JavaStatement caseStatement) {
this(new int[]{caseLabel}, caseStatement);
}
/**
* Constructor for an IntCaseGroup.
* @param caseLabels the case labels
* @param caseStatement
*/
public IntCaseGroup(int[] caseLabels, JavaStatement caseStatement) {
super(caseStatement);
this.caseLabels = caseLabels.clone();
}
/**
* Get the number of case labels in this group.
* @return the number of case labels.
*/
public int getNCaseLabels() {
return caseLabels.length;
}
/**
* Get the nth case label in this group.
* @param n the index of the case label to return.
* @return the nth case label in this group.
*/
public int getNthCaseLabel(int n) {
return caseLabels[n];
}
/**
* @return a copy of the array of case labels.
*/
public int[] getCaseLabels () {
int[] rv = new int[caseLabels.length];
System.arraycopy(caseLabels, 0, rv, 0, rv.length);
return rv;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitIntCaseGroup(this, arg);
}
}
/**
* A default case.
* @author Edward Lam
*/
public static final class DefaultCase extends SwitchCase {
/**
* Constructor for a DefaultCase.
* @param caseStatement
*/
public DefaultCase(JavaStatement caseStatement) {
super(caseStatement);
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitDefaultCase(this, arg);
}
}
}
/**
* A return statement.
* @author Edward Lam
*/
public static final class ReturnStatement extends JavaStatement {
/** The JavaExpression to return, or null if no value is returned. */
private final JavaExpression returnExpression;
/**
* Constructor for a ReturnStatement.
*/
public ReturnStatement() {
this.returnExpression = null;
}
/**
* Constructor for a ReturnStatement.
* @param returnExpression the JavaExpression to return, or null if no value is returned.
*/
public ReturnStatement(JavaExpression returnExpression) {
this.returnExpression = returnExpression;
}
/**
* Get the JavaExpression to return, or null if no value is returned.
* @return JavaExpression
*/
public JavaExpression getReturnExpression() {
return returnExpression;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitReturnStatement(this, arg);
}
}
public static final class ThrowStatement extends JavaStatement {
/** The JavaExpression to throw. */
private final JavaExpression thrownExpression;
/**
* Constructor for a ThrowStatement
* @param thrownExpression the JavaExpression to throw.
*/
public ThrowStatement (JavaExpression thrownExpression) {
this.thrownExpression = thrownExpression;
Assert.isNotNull(thrownExpression);
}
/**
* Get the java expression to throw.
* @return JavaExpression
*/
public JavaExpression getThrownExpression () {
return thrownExpression;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitThrowStatement(this, arg);
}
}
/**
* A JavaDoc comment.
* Note: this isn't really a Statement (as defined by Java)..
* @author Raymond Cypher
*/
public static final class JavaDocComment extends MultiLineComment {
/**
* Constructor for a multi line comment.
* @param lines
*/
public JavaDocComment (List<String> lines) {
super (lines);
}
/**
* Constructor for multi line comment.
* @param content
*/
public JavaDocComment (String content) {
super (content);
}
/**
* Constructor for multi line comment.
* @param other
*/
public JavaDocComment (MultiLineComment other) {
super (other);
}
/**
* Constructor for an empty JavaDocComment
*/
public JavaDocComment () {
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitJavaDocCommentStatement(this, arg);
}
}
/**
* A multi line comment.
* Note: this isn't really a Statement (as defined by Java)..
* @author Raymond Cypher
*/
public static class MultiLineComment extends Comment {
/** List of String.
* The lines of text in the comment. */
private final List<String> commentLines = new ArrayList<String>();
/**
* Constructor for a multi line comment.
* @param lines
*/
public MultiLineComment (List<String> lines) {
for (int i = 0, n = lines.size(); i < n; ++i) {
commentLines.add(lines.get(i));
}
}
/**
* Constructor for multi line comment.
* @param content
*/
public MultiLineComment (String content) {
// Break content in to lines.
StringTokenizer stk = new StringTokenizer (content, "\r\n");
while (stk.hasMoreTokens()) {
commentLines.add(stk.nextToken());
}
}
/**
* Constructor for multi line comment.
* @param other
*/
public MultiLineComment (MultiLineComment other) {
for (final String commentLine : other.getCommentLines()) {
this.addLine(commentLine);
}
}
/**
* Constructor for an empty multi-line comment.
*/
public MultiLineComment () {
}
/**
* @return an unmodifiable collection containing the individual lines
* of the comment as strings.
*/
public Collection<String> getCommentLines () {
return Collections.unmodifiableCollection(commentLines);
}
/**
* Add a line to the multi line comment.
* @param line
*/
public void addLine (String line) {
// Break content in to lines.
StringTokenizer stk = new StringTokenizer (line, "\r\n");
while (stk.hasMoreTokens()) {
commentLines.add(stk.nextToken());
}
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitMultiLineCommentStatement(this, arg);
}
}
/**
* A line comment.
* Note: this isn't really a Statement (as defined by Java)..
* @author Edward Lam
*/
public static final class LineComment extends Comment {
/** The text of the comment. */
private final String commentText;
/**
* Constructor for a line comment.
* @param commentText the text of the comment.
*/
public LineComment(String commentText) {
Assert.isNotNull(commentText);
this.commentText = commentText;
}
/**
* Get the text of the comment.
* @return String
*/
public String getCommentText() {
return commentText;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitLineCommentStatement(this, arg);
}
}
/**
* Base class for comments in the Java model.
* @author RCypher
*
*/
public static abstract class Comment extends JavaStatement {
}
/**
* Represents an unconditional loop. i.e. while (true) {...}
* @author RCypher
*
*/
public static final class UnconditionalLoop extends JavaStatement {
/**
* Label for the loop.
*/
private final String label;
/** Body of the loop. */
private final JavaStatement body;
public UnconditionalLoop (String label, JavaStatement body) {
this.label = label;
this.body = body;
}
/**
* @return Returns the body.
*/
public JavaStatement getBody() {
return body;
}
/**
* @return Returns the label.
*/
public String getLabel() {
return label;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitUnconditonalLoop(this, arg);
}
}
/**
* Represents a method invocation that is wrapped in a synchronized block.
* @author rcypher
*/
public static class SynchronizedMethodInvocation extends JavaStatement {
/** The method invocation. */
private final MethodInvocation methodInvocation;
/** The object that is being synchronized on. */
private final JavaExpression synchronizingObject;
/** Create a SynchronizedMethodInvocation that is being synchronized on
* a java field.
* @param methodInvocation
* @param synchronizingObject
*/
public SynchronizedMethodInvocation (MethodInvocation methodInvocation, JavaField synchronizingObject) {
// Check that the field in question is an object (i.e. we can't synchronize on a primitive type.)
if (methodInvocation == null || synchronizingObject == null || !synchronizingObject.getFieldType().isObjectReference()) {
throw new IllegalArgumentException("Illegal argument to SynchronizedMethodInvocation constructor.");
}
this.methodInvocation = methodInvocation;
this.synchronizingObject = synchronizingObject;
}
public MethodInvocation getMethodInvocation() {
return methodInvocation;
}
public JavaExpression getSynchronizingObject() {
return synchronizingObject;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitSynchronizedMethodInvocationStatement(this, arg);
}
}
/**
* Represents a labeled continue statement.
* @author RCypher
*/
public static final class LabelledContinue extends JavaStatement {
private final String label;
public LabelledContinue (String label) {
this.label = label;
}
public String getLabel () {
return label;
}
/**
* {@inheritDoc}
*/
@Override
public <T, R> R accept(JavaModelVisitor<T, R> visitor, T arg) {
return visitor.visitLabelledContinueStatement(this, arg);
}
}
}