blob: bf324ad47b9aba84063b8fff32b1f8e9b3d75cf1 [file] [log] [blame]
package org.eclipse.jem.internal.proxy.initParser;
/*******************************************************************************
* Copyright (c) 2001, 2003 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 Corporation - initial API and implementation
*******************************************************************************/
/*
* $RCSfile: Message.java,v $
* $Revision: 1.3 $ $Date: 2005/02/15 22:55:20 $
*/
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.jem.internal.proxy.common.AmbiguousMethodException;
import org.eclipse.jem.internal.proxy.common.MethodHelper;
public class Message extends Expression {
protected boolean trailingPeriod = false;
protected Method fMethod;
public Expression receiver;
public String message;
public boolean argsClosed = false;
public boolean insideArgsOpenedParen = false;
public boolean insideArgsClosedParen = false;
protected boolean isComplete = false;
public ArrayList arguments = new ArrayList(2);
public Message(Expression aReceiver , char[] token , ClassLoader aClassLoader){
receiver = aReceiver;
message = new String(token);
fClassLoader = aClassLoader;
}
public boolean isComplete(){
return isComplete;
}
/**
* Send the message to the receiver
*/
public Object evaluate() throws Exception {
cacheMethod();
// Get the array of arguments
Object[] args = new Object[arguments.size()];
Iterator itr = arguments.iterator();
for (int i = 0; i < arguments.size() ; i++){
Expression anExpression = (Expression)itr.next();
args[i] = anExpression.evaluate();
}
Object receiverValue = receiver.evaluate(); // So if evaluation exception thrown, we don't wrapper again.
try {
return fMethod.invoke(receiverValue, args);
} catch (Exception e) {
throw new EvaluationException(e);
}
}
/**
* Cache the message
*/
protected void cacheMethod() throws Exception {
if (fMethod == null) {
Class[] argTypes = new Class[arguments.size()];
Iterator itr = arguments.iterator();
for (int i=0; i<argTypes.length; i++)
argTypes[i] = getEvaluationTypeClass((Expression) itr.next());
try {
fMethod = MethodHelper.findCompatibleMethod(getEvaluationTypeClass(receiver), message, argTypes);
} catch (NoSuchMethodException e) {
throw new EvaluationException(e);
} catch (AmbiguousMethodException e) {
throw new EvaluationException(e);
}
}
}
/**
* getTypeClass method comment.
*/
public Class getTypeClass() throws Exception {
cacheMethod();
return fMethod.getReturnType();
}
protected String getTypeClassName() {
return ""; // If we got this far, we don't know what it is. //$NON-NLS-1$
}
/**
* push method comment.
*/
public Expression push(char[] token, char tokenDelimiter) {
// If we are closed and we receive a . with no token then remember this
if ( argsClosed && !trailingPeriod && tokenDelimiter == DelimiterPeriod && token.length == 0 ) {
trailingPeriod = true;
return this;
}
// If we have been closed with a . and we receive a . then we are a field
if ( trailingPeriod && tokenDelimiter == DelimiterPeriod ) {
return new Field(this,token,fClassLoader);
}
// If we have been closed with a . and we receive a ( we are a message
if ( trailingPeriod && tokenDelimiter == DelimiterOpenParen ) {
return new Message(this,token,fClassLoader);
}
// If we have been closed and we receive a , or a ) we are complete - this is a structural token intended for someone else,
// probably a message argument lower down the stack
if (argsClosed && (tokenDelimiter == DelimiterComma || tokenDelimiter == DelimiterCloseParen)){
isComplete = true;
return this;
}
// If the args are opened and a token was supplied then it must be an argument
//if ( argsOpened && ( tokenDelimiter == DelimiterCloseParen || tokenDelimiter == DelimiterComma ||
//tokenDelimiter == DelimiterSpace || tokenDelimiter == DelimiterQuote || tokenDelimiter == DelimiterPeriod)) {
if (!argsClosed){
if ( arguments.size() > 0 ){
Expression openArgument = (Expression)arguments.get(arguments.size()-1);
if ( !openArgument.isComplete() ) {
openArgument.push(token,tokenDelimiter);
// If the argument is complete and we received a ) then the message is complete
if ( openArgument.isComplete() && tokenDelimiter == DelimiterCloseParen){
argsClosed = true;
}
return this;
}
}
// We must have a new argument - process accordingly
Expression newArgument = null;
if (!insideArgsOpenedParen && tokenDelimiter == DelimiterOpenParen){
insideArgsOpenedParen = true;
newArgument = new Statement(fClassLoader).push(token,tokenDelimiter);
newArgument = new MessageArgument(newArgument);
arguments.add(newArgument);
}
if ( newArgument == null && (token.length > 0 || tokenDelimiter == DelimiterQuote || tokenDelimiter == DelimiterSingleQuote || tokenDelimiter == DelimiterOpenParen )) {
newArgument = new Statement(fClassLoader).push(token,tokenDelimiter);
newArgument = new MessageArgument(newArgument);
arguments.add(newArgument);
}
// If the token after the argument is a ) then the message is being closed
if ( !insideArgsOpenedParen && tokenDelimiter == DelimiterCloseParen ) {
argsClosed = true;
return this;
}
if ( insideArgsOpenedParen && tokenDelimiter == DelimiterCloseParen ) {
insideArgsClosedParen = true;
return this;
}
// If the token after the argument is a , or a ' ' then the argument is being closed
if ( tokenDelimiter == DelimiterComma || tokenDelimiter == DelimiterSpace ) {
return this;
}
// Otherwise the new argument is stil processing. Return it
// return newArgument;
}
// If we don't have a message yet, then consume this one
if ( message.length() == 0 ) {
message = new String(token);
return this;
}
return this;
}
public String toString(){
java.io.StringWriter writer = new java.io.StringWriter();
writer.write("Msg Name=\""); //$NON-NLS-1$
if ( message != null ) {
writer.write(message);
} else {
writer.write("UNNAMED"); //$NON-NLS-1$
}
writer.write("\" Rcv=("); //$NON-NLS-1$
if ( receiver != null ){
writer.write(receiver.toString());
} else {
writer.write("NONE"); //$NON-NLS-1$
}
writer.write(')');
if ( arguments != null ) {
writer.write("Args("); //$NON-NLS-1$
Iterator iter = arguments.iterator();
int i=1;
while(iter.hasNext()){
writer.write(new Integer(i).toString());
writer.write('(');
writer.write(iter.next().toString());
writer.write("),"); //$NON-NLS-1$
}
writer.write(')');
}
return writer.toString();
}
/**
* Is the message result a primitive.
*/
public boolean isPrimitive() throws Exception {
cacheMethod();
return fMethod.getReturnType().isPrimitive();
}
}