package com.net.tcp;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
* @author 鄭創坤
* actionscript 3 StreamObject生成器
*
*/
public class AS3Utils {
/**生成路徑*/
private String asClassPath = "as/com/net/test/";
/**生成包*/
private String asPack = "com.net.test";
private String imports[] = {
"import com.net.tcp.DataPack;",
"import com.net.tcp.DataType;",
"import com.net.tcp.StreamObject;",
"import com.commons.utils.Map;"
};
private String head = "public class {0} implements StreamObject";
private String var = "public var {0}:{1};";
private String suffix = ".as";
public AS3Utils(){
}
public void init(String asClassPath, String asPack){
this.asClassPath = asClassPath;
if(asPack != null){
this.asPack = asPack;
}
}
public void execute(Collection<Class<?>> classes) throws Exception{
File file = new File(asClassPath);
if(!file.exists()){
file.mkdirs();
}
if(file.exists()){
for(Class<?> c : classes){
File cf = new File(asClassPath + c.getSimpleName() + suffix);
if(cf.exists()){
cf.createNewFile();
}
FileOutputStream fos = new FileOutputStream(cf);
try{
fos.write(getASClass(c).getBytes("UTF-8"));
fos.flush();
}finally{
fos.close();
}
}
}
}
public String getASClass(Class<?> c){
StringBuffer sb = new StringBuffer();
int tab = 0;
sb.append(getLine("package " + asPack, tab));
sb.append(getLine("{", tab++));
for(String imp : imports){
sb.append(getLine(imp, tab));
}
sb.append(getLine(head.replace("{0}", c.getSimpleName()), tab));
sb.append(getLine("{", tab++));
Field[] fields = c.getDeclaredFields();
for(Field field : fields){
sb.append(getLine(getVar(field), tab));
}
sb.append(getLine(getDecode(c, tab), 0));
sb.append(getLine(getEncode(c, tab), 0));
sb.append(getLine("}", --tab));
sb.append(getLine("}", --tab));
return sb.toString();
}
public String getVar(Field f){
String s = var.replace("{0}", f.getName());
String classname = ((Class)f.getType()).getSimpleName();
if(DataType.isNumberByClassName(classname)){
s = s.replace("{1}", "Number");
}else if(classname.endsWith("List")){
s = s.replace("{1}", "Array");
}else{
s = s.replace("{1}", DataType.getObjectNameByClassName(classname));
}
return s;
}
public static String getLine(String line, int tabN){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < tabN; i++){
sb.append("\t");
}
sb.append(line).append("\n");
return sb.toString();
}
public String getDecode(Class<?> c, int tab){
DecodeUtils utils = new DecodeUtils();
return utils.getDecode(c, tab);
}
public String getEncode(Class<?> c, int tab){
EncodeUtils utils = new EncodeUtils();
return utils.getEncode(c, tab);
}
class DecodeUtils{
private String head = "public function decode(pack:DataPack):void{";
public String getDecode(Class<?> c, int tab){
Field[] fields = c.getDeclaredFields();
StringBuffer sb = new StringBuffer();
sb.append(AS3Utils.getLine(head, tab++));
for(int i = 0; i < fields.length; i++){
sb.append(AS3Utils.getLine(getFieldLine(fields[i]), tab));
}
sb.append(AS3Utils.getLine("}", --tab));
return sb.toString();
}
public String getFieldLine(Field field){
StringBuffer sb = new StringBuffer();
sb.append(field.getName())
.append(" = ")
.append(getRight(field))
.append(";");
return sb.toString();
}
private String getRight(Field field){
StringBuffer sb = new StringBuffer();
if(DataType.isNumberByClassName(field.getType().getSimpleName())){
sb.append("Number(pack.readObject())");
}else if(field.getType().getSimpleName().endsWith("List")){
sb.append("pack.readObject()")
.append(" as ")
.append(" Array ");
}else{
sb.append("pack.readObject()")
.append(" as ")
.append(DataType.getObjectNameByClassName(field.getType().getSimpleName()));
}
return sb.toString();
}
}
class EncodeUtils{
private String head = "public function encode(pack:DataPack):void{";
public String getEncode(Class<?> c, int tab){
Field[] fields = c.getDeclaredFields();
Method[] methods = c.getDeclaredMethods();
StringBuffer sb = new StringBuffer();
sb.append(AS3Utils.getLine(head, tab++));
for(int i = 0; i < fields.length; i++){
sb.append(AS3Utils.getLine(getFieldLine(fields[i], methods), tab));
}
sb.append(AS3Utils.getLine("}", --tab));
return sb.toString();
}
public String getFieldLine(Field field, Method[] methods){
StringBuffer sb = new StringBuffer();
sb.append("pack.writeObject(")
.append(field.getName());
List<String> types = this.getTypes(field, methods);
for(int i = 0; i < types.size(); i++){
sb.append(", ").append(types.get(i));
}
sb.append(");");
return sb.toString();
}
public List<String> getTypes(Field field, Method[] methods){
List<String> list = new ArrayList<String>();
list.add("DataType." + DataType.getTypeNameByClassName(field.getType().getSimpleName()));
if(field.getType().getSimpleName().endsWith("List")){
Type type = getMethod(methods, getFieldMethodName(field)).getGenericReturnType();
list.addAll(getTypes((ParameterizedType)type));
}
return list;
}
public List<String> getTypes(ParameterizedType type){
List<String> list = new ArrayList<String>();
if(type != null){
Type[] types = ((ParameterizedType)type).getActualTypeArguments();
Class<?> c = null;
Type[] types1 = null;
for(Type t : types){
if(t instanceof ParameterizedType){
types1 = ((ParameterizedType)t).getActualTypeArguments();
if(types1 != null){
if(((ParameterizedType)t).getRawType().toString().endsWith("List")){
list.add("DataType." + DataType.getTypeNameByClassName(((ParameterizedType)t).getRawType().toString()));
list.addAll(getTypes((ParameterizedType)t));
}
}
}else{
c = (Class<?>)t;
list.add("DataType." + DataType.getTypeNameByClassName(c.getSimpleName()));
}
}
}
return list;
}
public String getFieldMethodName(Field field){
String name = field.getName();
String h = name.substring(0, 1).toUpperCase();
String l = name.substring(1, name.length());
return "get" + h + l;
}
public Method getMethod(Method[] methods, String methodName){
for(Method method : methods){
if(method.getName().equals(methodName))
return method;
}
return null;
}
}
public static void main(String args[]) throws Exception{
StreamObjectManager.init("com.net.test.*");
AS3Utils utils = new AS3Utils();
utils.execute(StreamObjectManager.getClasses().values());
}
}