package jscript.expression;
import java.util.*;
import jscript.engine.*;
import jscript.exception.*;
import jscript.statement.*;
import jscript.util.*;
public class JScriptMethod {
public static final int NONE = 0;
public static final int PRIVATE = 1;
public static final int PROTECTED = 2;
public static final int PUBLIC = 3;
protected class Parameter {
public boolean isFinal;
public Class type;
public String name;
public Parameter(boolean isFinal, Class type, String name) {
this.isFinal = isFinal;
this.type = type;
this.name = name;
}
public String toString() {
return type + " " + name;
}
}
protected int privacy;
protected boolean isStatic;
protected boolean isAbstract;
protected boolean isFinal;
protected boolean isNative;
protected boolean isSynchronized;
protected Class type;
protected String name;
protected List throwList;
protected Statement body;
protected List paramList;
protected Class[] paramType;
public JScriptMethod() {
privacy = NONE;
isStatic = false;
isAbstract = false;
isFinal = false;
isNative = false;
isSynchronized = false;
paramList = new ArrayList();
throwList = null;
type = null;
name = null;
body = null;
paramType = null;
}
public void setPrivacy(int privacy) {
if (this.privacy == privacy)
throw new ParsingException("Duplicate modifier for the method");
if (this.privacy != NONE)
throw new ParsingException("The method can only set one of public / protected / private");
this.privacy = privacy;
}
public void setStatic(boolean isStatic) {
if (this.isStatic == isStatic)
throw new ParsingException("Duplicate modifier for the method");
this.isStatic = isStatic;
}
public void setAbstract(boolean isAbstract) {
throw new ParsingException("The abstract method can only be defined by an abstract class");
}
public void setFinal(boolean isFinal) {
if (this.isFinal == isFinal)
throw new ParsingException("Duplicate modifier for the method");
this.isFinal = isFinal;
}
public void setNative(boolean isNative) {
throw new ParsingException("The native method is not supported by jscript yet");
}
public void setSynchronized(boolean isSynchronized) {
if (this.isSynchronized == isSynchronized)
throw new ParsingException("Duplicate modifier for the method");
this.isSynchronized = isSynchronized;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setType(Class type) {
this.type = type;
}
public void addParameter(boolean isFinal, Class type, String name) {
paramList.add(new Parameter(isFinal, type, name));
}
public Class[] getParameterTypes() {
if (paramType != null) return paramType;
paramType = new Class[paramList.size()];
int i = 0;
for (Iterator it = paramList.iterator(); it.hasNext(); i++) {
Parameter p = (Parameter)it.next();
paramType[i] = p.type;
}
return paramType;
}
public List getParamList() {
return paramList;
}
public void setThrowList(List throwList) {
this.throwList = throwList;
}
public void setBody(Statement body) {
this.body = body;
}
public Object invoke(EvaluatingContext ctx, Object[] args) {
ctx.call();
try {
int i = 0;
for (Iterator it = paramList.iterator(); it.hasNext(); i++) {
Parameter p = (Parameter)it.next();
Class c = args[i] == null ? null : args[i].getClass();
if (c != null && p.type.isPrimitive()) {
c = (Class)PrimitiveType.primitiveClassMap.get(c);
if (c == null) c = args[i].getClass();
}
ctx.defineVariable(p.name, p.type, p.isFinal, null).setValue(args[i], c, ctx);
}
try {
body.execute(ctx);
return ctx.popReturnValue();
}catch(RuntimeException e) {
throw e;
}catch(Exception e) {
throw new InvokationException("Exception on invokation", e);
}
} finally {
ctx.ret();
}
}
public Class getReturnType() {
return type;
}
public String toString() {
StringBuffer sb = new StringBuffer();
if (privacy == JScriptMethod.PUBLIC) sb.append("public ");
if (privacy == JScriptMethod.PROTECTED) sb.append("protected ");
if (privacy == JScriptMethod.PRIVATE) sb.append("private ");
if (isStatic) sb.append("static ");
if (isAbstract) sb.append("abstract ");
if (isFinal) sb.append("final ");
if (isNative) sb.append("native ");
if (isSynchronized) sb.append("synchronized ");
sb.append(type + " ");
sb.append(name + "(");
int i = 0;
for (Iterator it = paramList.iterator(); it.hasNext();) {
if (i++ > 0) sb.append(",");
sb.append(it.next());
}
sb.append(")");
if (throwList != null && !throwList.isEmpty()) {
sb.append(" throws ");
i = 0;
for (Iterator it = throwList.iterator(); it.hasNext();) {
if (i++ > 0) sb.append(",");
sb.append(it.next());
}
}
return sb.toString();
}
}