项目中需要将以前的java代码转到flex中,手动写非常费劲.然后用baidu搜,csnd上有资源,但杯具的发现全都要资源分,而更杯具的是自己的资源分已经是负数.只能感慨了一下国人的开源精神和奉献精神又创新低.
google搜,无果.
最后用俺相当烂的英语拼了一下"Converting Java to ActionScript 3" 没想到竟然找到了.只恨百度不争气,甘做井底之蛙.csdn太功利,外国的开源项目到它那就要积分了.悲哀.最后,就恨自己英语太差了.不想看老外的文章……
言归正传,最终发现了J2AS3 这个开源项目,地址如下:http://code.google.com/p/j2as3/
一老外写的,不过有一些缺陷,就是对java的泛型支持的不是太好,不能转换泛型.
又在网上搜了一下啊,发现有一个哥们已经使用过并且写出了十分不错的使用行的.在此表示敬意.
地址如下:http://blog.sina.com.cn/s/blog_67532f7c0100ozbv.html
全文如下:
有些情况下我们需要将Java类转换成AS3类,比如使用Flash Remoting时,为了方便映射,我们会在AS3中定义与Java后台相关的值对像,用于序列化与反序列化。如果要互通的类有很多,手工去建立这两端的类太麻烦了。
在网上搜到了一个将Java 类文件转换为AS3类文件的开源项目,J2as3:http://code.google.com/p/j2as3/
在使用这个工具转换由Jaxb生的ImsQti_v2p1规范中的java类为as3类时,还是由一些不完美之处。主要是由于在Java类大量的使用List泛型,J2as3并不支持这个转换,目前作者还在进行修改。
下面就是我对J2as3的代码进行一些修改,以方便在BlazeDs4环境中使用。
修改的代码位置是J2AS3Application.as的convertFile函数中,这个方法读取java类文件,并通过转换器将文件内容转换,然后再重新生成新的as类文件。
var converter:Converter = new Converter(code);
var as3Code:String = converter.getNewClass();
其中的as3Code将为转换后的代码。在将as3Code生成类文件之前,进行我的处理。在此本人并不深入到converter内部去逐个处理,而是直接在as3Code上使用正则表达式来处理。本文是在Jaxb生成的imsqti_v2p1规范的java类转换成适用于BlazeDS与Flash间值对象映射的情景下练习用的,并未优化,也不考虑通用场景,切勿生搬硬套到别的场合。
1、List<type>的转换 。
默认情况下,对于无法识别的AS3语法之外的字符串,J2AS3会保留不动,BlazeDS的官方文档中描述到Java中的List类型在AS3中可以使用Array来映射。在Flex中,我使用mx.collections.ArrayCollection类来映射。
例如protected List<Serializable> content;要转换成:protected var content :ArrayCollection;
实现代码:
myPattern=/List<(\w+)> (\w+);/g;
as3Code=as3Code.replace(myPattern,"var $2 :ArrayCollection;");
其中的myPattern为RegExp类。
()表示是使用组;这样可以在替换时使用$1,$2来引用匹配的串;
“组是模式的子部分。您可以使用组实现以下操作:
■ 将数量表示符应用到多个字符。
■ 界定要应用逻辑“或”(通过使用 | 字符)的子模式。
■ 捕获正则表达式中的子字符串匹配(例如,在正则表达式中使用 \1 以匹配先前匹配的
组,或类似地在 String 类的 replace() 方法中使用 $1)。”
\w用法:匹配单词字符(A-Z、a-z、0-9 或 _)
/g表现全局,对as3Code全串进行查找。“指定是否为正则表达式使用全局匹配。如果 global == true
,找到一个匹配项后将设置 lastIndex
属性。下次请求查找匹配项时,此正则表达式引擎将从字符串中的 lastIndex
位置开始查找。构造正则表达式时,使用 g
标志将 global
设置为true
。”
2、将protected改为public
之所以这样做是因为 Jaxb自动生成的imsqti_v2p1类的成员变量是protected的,然后通过get/set来实现读写,这对于与Flash端的序列化有影响,为了方便两者互操作,统统将成员变量变成public,
实现代码:
myPattern= /protected/gi;
as3Code=as3Code.replace(myPattern,"public");
3、在AS3中做valueObject的映射
要指定远程对象的别名,即如下形式:
[RemoteClass(alias="edu.lltang.jaxb.imsqti_v2p1.AbbrType")]
public class AbbrType {
在做转换时,可以这样实现:
myPattern=/public class (\w+) {/g;
as3Code=as3Code.replace(myPattern,"[Bindable]\n[RemoteClass(alias="edu.lltang.jaxb.imsqti_v2p1.$1")]\npublic class $1 {");
4、枚举类型
关于AS中的枚举,AS3官方文档是这样描述的:
“枚举”是您创建的一些自定义数据类型,用于封装一小组值。ActionScript 3.0 并不支持具体的枚举工具,这与 C++ 使用 enum 关键字或 Java 使用 Enumeration 接口不一样。不过,您可以使用类或静态常量创建枚举。例如,ActionScript 3.0 中的 PrintJob 类使用名为 PrintJobOrientation 的枚举来存储由 "landscape" 和"portrait" 组成的一组值,如下面的代码所示:
public final class PrintJobOrientation { public static const LANDSCAPE:String = "landscape"; public static const PORTRAIT:String = "portrait"; }
按照惯例,枚举类是使用 final 属性声明的,因为不需要扩展该类。该类仅由静态成员组成,这表示不创建该类的实例。而是直接通过类对象来访问枚举值。
先看Java类:
public enum CardinalityType {
@XmlEnumValue("multiple")
MULTIPLE("multiple"),
@XmlEnumValue("ordered")
ORDERED("ordered"),
@XmlEnumValue("record")
RECORD("record"),
@XmlEnumValue("single")
SINGLE("single");
private final String value;
CardinalityType(String v) {
value = v;
}
public String value() {
return value;
}
public static CardinalityType fromValue(String v) {
for (CardinalityType c: CardinalityType.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
改变成:
public final class CardinalityType {
public static const MULTIPLE:String = "multiple";
public static const ORDERED:String = "ordered";
public static const RECORD:String = "record";
public static const SINGLE:String = "single";
}
实现代码:(如下代码是根据Jaxb生成java类而改的,并未优化,切勿生搬硬套到别的场合。)
if(as3Code.indexOf("enum")!=-1)
{
as3Code="package edu.lltang.qti.as3{\n"+as3Code+"}";
myPattern=/public enum (\w+) {/g;
as3Code=as3Code.replace(myPattern,"public final class $1 {");
li=as3Code.indexOf("private",0);
as3Code=as3Code.substring(0,li);
as3Code+="}"
myPattern=/(\w+)\("(\w+)"\),/g;
as3Code=as3Code.replace(myPattern,"public static const $1:String = "$2";");
myPattern=/(\w+)\("(\w+)"\);/g;
as3Code=as3Code.replace(myPattern,"public static const $1:String = "$2";");
}else
{
5、Double
J2AS3在关键字列表(Tokenizer.as)中没有包含Double(有double),在进行查找时,虽然能匹配,但转换的时候,没有将Double转换成Number。
public var lowerBound:Double;
这样的转换会造成编译错误。
在Converter.as的toASType方法中,将:
if (type == "double" || type == "float" )
return "Number";
改为:
if (type == "double" || type == "float" || type=="Double")
return "Number";
即可。
附:jaxb>Imsqti_v2p1.xsd->Java Class->AS3 Class,加在J2AS3项目的J2AS3Application类的convertFile方法末。
//lltang
var myPattern:RegExp = / ,/gi;
var li:int=as3Code.indexOf("*/",0);
as3Code=as3Code.substring(li+2,as3Code.length);
li=as3Code.indexOf("/*",0);
as3Code=as3Code.substr(0,li);
as3Code+="}";
as3Code=as3Code.replace(myPattern,"");
as3Code=as3Code.replace("})","");
//如果是枚举类:
if(as3Code.indexOf("enum")!=-1)
{
as3Code="package edu.lltang.qti.as3{\n"+as3Code+"}";
myPattern=/public enum (\w+) {/g;
as3Code=as3Code.replace(myPattern,"public final class $1 {");
li=as3Code.indexOf("private",0);
as3Code=as3Code.substring(0,li);
as3Code+="}\n}";
myPattern=/(\w+)\("(\w+)"\),/g;
as3Code=as3Code.replace(myPattern,"public static const $1:String = "$2";");
myPattern=/(\w+)\("(\w+)"\);/g;
as3Code=as3Code.replace(myPattern,"public static const $1:String = "$2";");
}else
{
as3Code="package edu.lltang.qti.as3{\n import mx.collections.ArrayCollection;\n"+as3Code+"}";
myPattern= /protected/gi;
as3Code=as3Code.replace(myPattern,"public");
myPattern=/List<(\w+)> (\w+);/g; //demo:List<Serializable> content->var content :ArrayCollection
as3Code=as3Code.replace(myPattern,"var $2 :ArrayCollection;");
//添加映射类
myPattern=/public class (\w+) {/g;
as3Code=as3Code.replace(myPattern,"[Bindable]\n[RemoteClass(alias="edu.lltang.jaxb.imsqti_v2p1.$1")]\npublic class $1 {");
}
//trace(as3Code);