package com.hexin.study.interpreter;
import com.hexin.study.util.Log;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
/**
* @author Administrator
*
* 更改所生成类型注释的模板为
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/
public class ClassTranslation implements Translation{
private String descriptor = null;//说明
private String flag = "false";
private String _extends = "";
private String implement = "";
private String interfaces = "";
private String superClass = "";
private String packageName = null;
private List importList = new ArrayList();
private String accessFlag = null;
private String _class = null;
private String className = null;
private List fieldList = new ArrayList();
private List methodList = new ArrayList();
private List table = null;
/* (非 Javadoc)
* @see com.hexin.study.interpreter.Translation#translate()
*/
public void translate(Context c) {
ClassContext cc = (ClassContext)c;
if(cc.getMAGIC().equals("CAFEBABE")){
table = cc.getCONSTANT_POOL();
translateClass(cc);
} else{
descriptor = "不是java class,无法解析";
}
}
/* (非 Javadoc)
* @see com.hexin.study.interpreter.Translation#print()
*/
public void print() {
if(descriptor == null){
VelocityEngine ve = new VelocityEngine();
Template t = null;
try {
ve.init();
t = ve.getTemplate("SourceFile.vm");
VelocityContext context = new VelocityContext();
context.put("flag",flag);
context.put("packageName",packageName);
context.put("importList",importList);
context.put("accessFlag",accessFlag);
context.put("extends",_extends);
context.put("implement",implement);
context.put("interfaces",interfaces);
context.put("superClass",superClass);
context.put("class",_class);
context.put("className",className);
context.put("fieldList",fieldList);
context.put("methodList",methodList);
StringWriter writer = new StringWriter();
t.merge(context,writer);
Log.info(writer.toString());
} catch (Exception e) {
e.printStackTrace();
}
} else{
Log.info(descriptor);
}
}
private void translateClass(ClassContext cc){
String str = (String)table.get(cc.getTHIS_CLASS()-1);
int classId = Integer.parseInt(str);
String tmp = (String)table.get(classId-1);
tmp = tmp.replaceAll("/",".");
int i = tmp.lastIndexOf(".");
packageName = tmp.substring(0,i);
className = tmp.substring(i+1);
if(packageName!=null && !packageName.equals(""))
flag = "true";
accessFlag = getClassAccess(cc.getACCESS_FLAGS());
superClass = getSuperClass(cc);
interfaces = getInterfaces(cc);
getMethodList(methodList,cc);
}
private String getClassAccess(short s){
StringBuffer sb = new StringBuffer();
short ACC_PUBLIC = 0x0001;
short ACC_FINAL = 0x0010;
short ACC_SUPER = 0x0020;
short ACC_INTERFACE = 0x0200;
short ACC_ABSTRACT = 0x0400;
if((s & ACC_PUBLIC) == ACC_PUBLIC)
sb.append("public");
if((s & ACC_FINAL) == ACC_FINAL)
sb.append(" final");
if((s & ACC_INTERFACE) == ACC_INTERFACE){
_class = "interface";
} else if((s & ACC_ABSTRACT) == ACC_ABSTRACT){
sb.append(" abstract");
_class = "class";
}
return sb.toString();
}
private String getSuperClass(ClassContext cc){
StringBuffer sb = new StringBuffer();
String str = (String)table.get(cc.getSUPER_CLASS()-1);
int classId = Integer.parseInt(str);
String tmp = (String)table.get(classId-1);
tmp = tmp.replaceAll("/",".");
if(!tmp.trim().equals("java.lang.Object")){
_extends = "extends";
int i = tmp.lastIndexOf(".");
importList.add(tmp.substring(0,i));
sb.append(" "+tmp.substring(i+1));
}
return sb.toString();
}
private String getInterfaces(ClassContext cc){
StringBuffer sb = new StringBuffer();
if(cc.getINTERFACES_COUNT()==0) return "";
if(_class.equals("interface")) implement = "extends ";
else implement = "implements ";
for(int i=0;i<cc.getINTERFACES_COUNT();i++){
int index = Integer.parseInt((String)cc.getINTERFACES().get(i));
int m = Integer.parseInt((String)table.get(index-1));
String str = (String)table.get(m-1);
str = str.replaceAll("/",".");
String tmp = getObject(str);
sb.append(tmp+",");
}
int length = sb.toString().length();
return sb.toString().substring(0,length-1);
}
private void getMethodList(List l,ClassContext cc){
List tmp = cc.getMETHODS();
int i = tmp.size();
for(int m=0;m<i;m++){
MethodNode mn = (MethodNode)tmp.get(m);
ClassMethod cm = new ClassMethod();
cm.setAccessFlag(getMethodAccess(mn.getAccessFlags()));
cm.setName((String)table.get(mn.getNameIndex()-1));
String str = (String)table.get(mn.getDescriptorIndex()-1);
parseMethodParamAndType(cm,str);
l.add(cm);
}
}
private void parseMethodParamAndType(ClassMethod cm,String str){
str = str.replaceAll("/",".");
int i = str.indexOf(")");
String tmpType = str.substring(i+1);
cm.setType(getMethodType(tmpType));
if(_class.equals("interface")) cm.setBody(";");
String tmpParam = str.substring(1,i);
cm.setParam(getMethodParam(tmpParam));
}
private String getMethodParam(String str){
if(str.equals("")) return "";
StringBuffer sb = new StringBuffer();
byte[] b = str.getBytes();
int count = 0;//记录数组维度
int object = 0;//记录对象其实位置
int objectCount = 1;//记录对象个数
for(int i=0;i<b.length;i++){
switch(b[i]){
case 'B':
sb.append("byte"+getVD(count)+" b,");
count = 0;
break;
case 'C':
sb.append("char"+getVD(count)+" ch,");
count = 0;
break;
case 'D':
sb.append("double"+getVD(count)+" d,");
count = 0;
break;
case 'F':
sb.append("float"+getVD(count)+" f,");
count = 0;
break;
case 'I':
sb.append("int"+getVD(count)+" i,");
count = 0;
break;
case 'J':
sb.append("long"+getVD(count)+" l,");
count = 0;
break;
case 'S':
sb.append("short"+getVD(count)+" s,");
count = 0;
break;
case 'Z':
sb.append("boolean"+getVD(count)+" bool,");
count = 0;
break;
case 'L':
object = i+1;
for(;b[object]!=';';object++);
String tmp = new String(b,i,object-i+1);
sb.append(getObjectType(tmp)+getVD(count)+" o"+objectCount+",");
objectCount += 1;
count = 0;
i = object;
break;
case '[':
count++;
break;
case 'V':
return "void";
}
}
int length = sb.toString().length();
return sb.toString().substring(0,length-1);
}
private String getVD(int count){//数组维度
if(count == 0) return "";
StringBuffer sb = new StringBuffer();
for(int m=0;m<count;m++)
sb.append("[]");
return sb.toString();
}
private String getMethodType(String str){
int i = str.lastIndexOf('[');
int count = i+1;
String tmp = getVD(count);
char c = str.charAt(i+1);
switch(c){
case 'B': return "byte"+tmp;
case 'C': return "char"+tmp;
case 'D': return "double"+tmp;
case 'F': return "float"+tmp;
case 'I': return "int"+tmp;
case 'J': return "long"+tmp;
case 'S': return "short"+tmp;
case 'Z': return "boolean"+tmp;
case 'L': return getObjectType(str)+tmp;
default: return "void";
}
}
private String getObjectType(String str){
int i = str.indexOf('L');
str = str.substring(i+1,str.length()-1);//清楚干扰信息"Ljava.lang.String;
String tmp = getObject(str);
return tmp;
}
private String getObject(String str){
int index = str.lastIndexOf('.');
String tmp = str.substring(index+1);
if((str.indexOf("java.lang")==-1)&&!(str.indexOf(packageName+".")!=-1)){
importList.add(str);
}
return tmp;
}
private String getMethodAccess(short s){
StringBuffer sb = new StringBuffer();
short ACC_PUBLIC = 0x0001;
short ACC_PRIVATE = 0x0002;
short ACC_PROTECTED = 0x0004;
short ACC_STATIC = 0x0008;
short ACC_FINAL = 0x0010;
short ACC_SYNCHRONIZED = 0x0020;
short ACC_NATIVE = 0x0100;
short ACC_ABSTRACT = 0x0400;
short ACC_STRICT = 0x0800;
if((s & ACC_PUBLIC) == ACC_PUBLIC)
sb.append("public");
if((s & ACC_PROTECTED) == ACC_PROTECTED)
sb.append("protected");
if((s & ACC_PRIVATE) == ACC_PRIVATE)
sb.append("private");
if((s & ACC_FINAL) == ACC_FINAL)
sb.append(" final");
if((s & ACC_STATIC) == ACC_STATIC)
sb.append(" static");
if((_class.indexOf("interface")==-1) && ((s & ACC_ABSTRACT) == ACC_ABSTRACT))
sb.append(" abstract");
return sb.toString();
}