/*
* JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.geequery.codegen.ast;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import com.github.geequery.codegen.ast.IClass.RealClass;
import jef.jre5support.script.JavaScriptUtil;
import jef.tools.ArrayUtils;
import jef.tools.string.JefStringReader;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class JavaMethod extends DefaultJavaElement implements JavaElement {
private String name;
private int modifier = 1;
private IClass returnType;
private Map<String, JavaParameter> inputArgs = new LinkedHashMap<String, JavaParameter>();
private List<IClass> throws_ = new ArrayList<IClass>();
private boolean varArg = false;
private boolean checkReturn = true;
private String[] typeParameters;
public IClass getReturnType() {
return returnType;
}
public void clearInputArgs(){
inputArgs.clear();
}
/**
* 按序号获取,从0开始
* @param index
* @return
*/
public JavaParameter getParameter(int index){
String key=inputArgs.keySet().toArray(new String[0])[index];
return getParameter(key);
}
/**
* 按名称获取
* @param name
* @return
*/
public JavaParameter getParameter(String name){
return inputArgs.get(name);
}
/**
* 获取所有参数的类型
* @return
*/
public IClass[] getParameterTypes() {
List<IClass> types=new ArrayList<IClass>();
for(JavaParameter p:inputArgs.values()){
types.add(p.getType());
}
return types.toArray(new IClass[inputArgs.size()]);
}
/**
* 增加一个泛型定义
* @param typeParameter
*/
public void addTypeParameter(String typeParameter) {
this.typeParameters = ArrayUtils.addElement(typeParameters, typeParameter);
}
public String[] getTypeParameters() {
return typeParameters;
}
public void setTypeParameters(String[] typeParameters) {
this.typeParameters = typeParameters;
}
public boolean isCheckReturn() {
return checkReturn;
}
public void setCheckReturn(boolean checkReturn) {
this.checkReturn = checkReturn;
}
public boolean isVarArg() {
return varArg;
}
public void setVarArg(boolean varArg) {
this.varArg = varArg;
}
public void setAbstract(boolean isAbstract) {
if (isAbstract != isAbstract()) {
modifier ^= Modifier.ABSTRACT;
}
}
public boolean isAbstract() {
return Modifier.isAbstract(modifier);
}
public JavaMethod(String name) {
this.name = name;
}
public void setModifier(int modifier) {
this.modifier = modifier;
}
public void setReturnType(IClass type) {
this.returnType = type;
}
public void setReturnType(String javaType) {
if ("void".equals(javaType)) {
this.returnType = null;
} else {
this.returnType = StringUtils.isEmpty(javaType) ? null : IClassUtil.getIClass(javaType);
}
}
public void setReturnType(Class<?> javaType) {
this.returnType = (javaType == null || javaType == Void.class) ? null : new RealClass(javaType);
}
public JavaParameter addparam(IClass type, String argname, int modifiers) {
JavaParameter p = new JavaParameter(this,argname,type, modifiers);
inputArgs.put(argname, p);
return p;
}
public JavaParameter addparam(Class<?> javaType, String argname) {
return addparam(new RealClass(javaType), argname, 0);
}
public JavaParameter addparam(String javaType, String argname) {
return addparam( IClassUtil.getIClass(javaType), argname, 0);
}
public JavaParameter addparam(String javaType, String argname, int modifier) {
return addparam( IClassUtil.getIClass(javaType), argname, modifier);
}
public void addThrows(Class<? extends Throwable> t) {
throws_.add(new RealClass(t));
}
public void addThrows(String t) {
throws_.add( IClassUtil.getIClass(t));
}
//private String code = null;
public List<IClass> getThrows() {
return throws_;
}
// 当使用toCode方法生成imports时已经太迟了,所以生成要提前
public void buildImport(JavaUnit javaUnit) {
super.buildImport(javaUnit);
toCode(javaUnit);
}
// public void clear() {
// this.code = null;
// }
public String toCode(JavaUnit main) {
// if (code != null)
// return code;
StringBuilder sb = new StringBuilder();
// 生成注释
sb.append(super.generateComments());
// 生成Annotation
if (this.getAnnotation() != null) {
for (String s : annotation) {
sb.append(s);
sb.append("\r\n\t");
// line++;
}
}
JavaUnit.appendModifier(sb, this.modifier,main.isInterface());
if (typeParameters != null && typeParameters.length > 0) {
sb.append("<");
for (int n = 0; n < typeParameters.length; n++) {
if (n > 0)
sb.append(',');
sb.append(typeParameters[n]);
}
sb.append(">");
}
if (returnType == null) {
sb.append("void ");
} else {
sb.append(main.getJavaClassName(returnType)).append(" ");
}
sb.append(name);
sb.append("(");
if (!inputArgs.isEmpty()) {
Iterator<String> iter = inputArgs.keySet().iterator();
String key = iter.next(); // key形参名
JavaParameter param = inputArgs.get(key);
param.genetateCode(this, main, sb,varArg && !iter.hasNext());
for (; iter.hasNext();) {
key = iter.next();
sb.append(",");
param = inputArgs.get(key);
if (param == null)
continue;
param.genetateCode(this, main, sb,varArg && !iter.hasNext());
}
}
sb.append(")");
// 添加异常定义
if (this.throws_ != null && throws_.size() > 0) {
sb.append("throws ");
for (int i = 0; i < throws_.size(); i++) {
if (i > 0)
sb.append(',');
IClass t = throws_.get(i);
sb.append(main.getJavaClassName(t));
}
}
if (Modifier.isAbstract(this.modifier) || main.isInterface()) {
sb.append(";");
return sb.toString();
}
sb.append("{\r\n");
boolean hasReturn = false;
for (String str : super.getContent()) {
sb.append("\t\t");
sb.append(str).append("\r\n");
if (checkReturn && str.startsWith("return ")) {
hasReturn = true;
}
}
if (checkReturn && returnType != null && !hasReturn) {
sb.append("\t\treturn "+IClassUtil.defaultValue(returnType)+";\n");
}
sb.append("\t}\r\n");
return sb.toString();
}
static String toMethodKey(String name, IClass... inputArgs) {
StringBuilder sb = new StringBuilder();
sb.append(name).append('(');
if (inputArgs.length > 0) {
for (IClass clz : inputArgs) {
sb.append(clz.getSimpleName());
sb.append(',');
}
sb.setLength(sb.length() - 1);
}
sb.append(')');
String key=sb.toString();
return key;
}
static String toMethodKey(String name, List<IClass> inputArgs) {
return toMethodKey(name, inputArgs.toArray(new IClass[inputArgs.size()]));
}
public String getKey() {
List<IClass> set=new ArrayList<IClass>();
for(JavaParameter jp:inputArgs.values()){
set.add(jp.getType());
}
return toMethodKey(name, set);
}
private ScriptEngine engine;
public String getName() {
return name;
}
public int getModifier() {
return modifier;
}
public void putAttribute(String key,Object value){
if(engine==null){
initEngine();
}
engine.put(key, value);
}
public String appendCode(String code){
try{
if(engine==null){
initEngine();
}
JefStringReader reader=new JefStringReader(code);
StringBuilder sb=new StringBuilder();
int c;
while((c=reader.read())>-1){
char ch=(char)c;
if(ch=='$'){
String varName=new String(reader.readUntillKey("$").toCharArray());
if(varName.length()>0){
reader.read();//跳过结束符
Object obj=engine.eval(varName);
obj=JavaScriptUtil.jsToJava(obj);
sb.append(ObjectUtils.toString(obj));
}
}else if(ch=='\''){
sb.append("\"");
}else{
sb.append(ch);
}
}
String str=sb.toString();
super.addContent(str);
return str;
}catch(IOException e){
throw new RuntimeException(e);
}catch(ScriptException e){
throw new RuntimeException(e);
}
}
private void initEngine() {
engine=jef.jre5support.script.JavaScriptUtil.newEngine();
}
}