/*******************************************************************************
* Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC, Canada.
* 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:
* The Chisel Group, University of Victoria
*******************************************************************************/
package ca.uvic.chisel.diver.sequencediagrams.sc.java.model;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
/**
* A class representing a message from one java object to another. This can be
* a method call, a return, or a throw.
* @author Del Myers
*/
public class JavaMessage implements IAdaptable, IJavaCallModel {
private JavaCallTree tree;
private ASTNode representingNode;
private IJavaElement element;
private IJavaActivation origin;
private IJavaActivation target;
private List<TryStatement> tries;
private IType type;
private boolean exception;
private String typeString;
public JavaMessage(JavaCallTree tree, ASTNode representingNode, IJavaActivation origin, IJavaActivation target) {
this.tree = tree;
this.representingNode = representingNode;
this.origin = origin;
this.target = target;
if (!(
(representingNode instanceof MethodInvocation) ||
(representingNode instanceof SuperMethodInvocation) ||
(representingNode instanceof ConstructorInvocation) ||
(representingNode instanceof ClassInstanceCreation) ||
(representingNode instanceof SuperConstructorInvocation) ||
(representingNode instanceof ReturnStatement) ||
(representingNode instanceof ThrowStatement) ||
(representingNode instanceof MethodDeclaration)
)) {
throw new IllegalArgumentException();
}
}
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (ASTNode.class.isAssignableFrom(adapter)) {
return getAST();
}
if (getJavaElement() != null) {
return getJavaElement().getAdapter(adapter);
}
return null;
}
public ASTNode getAST() {
return representingNode;
}
public IJavaElement getJavaElement() {
if (element == null) {
IMethodBinding binding = null;
if (getAST() instanceof MethodInvocation) {
binding = ((MethodInvocation)getAST()).resolveMethodBinding();
} else if (getAST() instanceof SuperMethodInvocation) {
binding = ((SuperMethodInvocation)getAST()).resolveMethodBinding();
} else if (getAST() instanceof ConstructorInvocation) {
binding = ((ConstructorInvocation)getAST()).resolveConstructorBinding();
} else if (getAST() instanceof SuperConstructorInvocation) {
binding = ((SuperConstructorInvocation)getAST()).resolveConstructorBinding();
} else if (getAST() instanceof ClassInstanceCreation) {
binding = ((ClassInstanceCreation)getAST()).resolveConstructorBinding();
} else if (getAST() instanceof ReturnStatement) {
return type;
} else if (getAST() instanceof ThrowStatement) {
return type;
} else if (getAST() instanceof MethodDeclaration) {
return target.getJavaElement();
}
if (binding != null) {
element = binding.getJavaElement();
} else {
element = type;
}
}
return element;
}
public JavaCallTree getTree() {
return tree;
}
/**
* @param list
*/
void setTries(List<TryStatement> list) {
this.tries = list;
}
/**
* Returns true if this message was passed within a try block that catches the given
* type.
* @param type
* @return
*/
public boolean catches(IType type) {
if (tries == null) {
return false;
}
for (TryStatement statement : tries) {
for (Object o : statement.catchClauses()) {
CatchClause catcher = (CatchClause) o;
ITypeBinding binding = catcher.getException().getType().resolveBinding();
if (binding != null) {
IType caughtType = (IType) binding.getJavaElement();
if (caughtType != null) {
try {
ITypeHierarchy hierarchy = caughtType.newSupertypeHierarchy(new NullProgressMonitor());
if (caughtType.equals(type) || hierarchy.contains(type)) {
return true;
}
} catch (JavaModelException e) {
}
}
}
}
}
return false;
}
/**
* @return
*/
public IJavaActivation getSource() {
return origin;
}
/**
* @return
*/
public IJavaActivation getTarget() {
return target;
}
/**
* @param thrown
*/
public void setType(IType type) {
this.type = type;
}
/**
* @param b
*/
public void setException(boolean b) {
this.exception = b;
}
/**
* @return the exception
*/
public boolean isException() {
return exception;
}
/**
* Sets the type to the given string representation.
* @param returnType
*/
public void setType(String returnType) {
this.typeString = returnType;
}
@Override
public String toString() {
if (type != null) {
return type.getElementName();
}
if (typeString != null) {
return Signature.toString(typeString);
}
return super.toString();
}
}