`
zhangziyangup
  • 浏览: 1078398 次
文章分类
社区版块
存档分类
最新评论

使用 JET 在 Eclipse 中创建更多更好的代码,如何掌握专家的最佳实践并提高您的模型驱动开发进度

 
阅读更多

代码生成不是一个新概念。它出现有一段时间了,而且作为提高生产力的一种方式,随着模型驱动开发(MDD)的发展而普及开来。Eclipse 项目有一个称为 JET 的技术项目就是一个专门的代码生成器。JET 所能生成的不仅仅是 “代码”,无论如何,在本文中我们称这些非编码的物件为工件(artifiact)

JET?EMF?JET2?
JET 新用户需要知道的一件重要事情是这里所讨论的 JET 版本是指 JET 的最新版本,通常是 JET2。在 Eclipse Modeling Framework(EMF)项目中 EMF 还使用一个较旧的 JET 版本来生成代码。JET2 是最新版本,也是新的 Eclipse Modeling Framework Technology(EMFT)项目的一部分。如果您对旧版本的 JET 感兴趣,请参阅 参考资料

开始

在本节中,我们将介绍 JET 项目设置基础,讨论 JET 项目的结构,然后运行一个快速转换。

创建一个 JET 项目

在实际接触 JET 之前,我们需要创建一个项目。使用创建项目的标准 Eclipse 方法来实现。就 JET 来说,使用命令 File > New > Other > EMFT JET Transformations > EMFT JET Transformation Project(请参见图 1)创建一个 EMFT JET Transformation Project。


图 1. JET 项目向导
JET 项目向导

JET 项目结构

让我们分析项目结构来搞清楚 JET 是如何工作的。在上面的部分,我们创建了一个 JET 项目(参见图 2)。在该 JET 项目中,我们需要浏览六个文件。


图 2. JET 项目结构
JET 项目结构

Eclipse 项目文件(MANIFEST.MF, plugin.xml, build.properties)
这是使用 Eclipse 项目时所创建的标准文件。对于这些文件需要注意的一件重要事情是:在 plugin.xml 中,JET 将自动添加 org.eclipse.jet.transform。通过扩展该扩展点,我们让 JET 知道我们在提供一个 JET 转换。
控制和模板文件(dump.jet, main.jet)
这是在转换中所使用的模板和控制文件。将在下面的概念部分讨论其细节。
输入模型(sample.xml)
这里我们可以看到用于转换的一个示例输入文件。注意该输入可以来自任何源,并不限于项目。

更改启动模板
默认情况下,JET 定义启动模板为 main.jet。该选项可在 plugin.xml(org.eclipse.jet.transform extension)中的 startTemplate 属性下配置。在该扩展下还有其他配置选项,可随意浏览。

运行 JET 转换

一旦有了一个项目,拥有合适的模板、控制文件和一个输入模型,我们就可以运行转换。通过熟悉的 Eclipse 概念 —— 启动配置(参见图 3),JET 提供了一个方便的方式来调用转换。要访问 JET 启动配置,我们转到 Run > JET Transformation,填充合适的选项,然后单击 Run


图 3. JET 启动配置
JET 启动配置

概念

JET 是指定模板输出工件的语言。实现一些应用程序的模板集合被称为蓝图(blueprint)(用我们的术语)。JET 范例可以用下列等式表示:

参数 + 蓝图 = 所需的工件

蓝图是由 JET 创建的,而参数是由蓝图用户提供的。蓝图由三个不同的文件集组成:

1. 参数
用于蓝图的参数使用 XML 格式。这赋予它强大的表现力,因为 XML 允许使用层次化关系、允许每个节点具有属性。输入参数被称为输入模型。蓝图将定义描述其期望参数的模式。例如,下面是蓝图创建网络嗅探器的输入实例:

清单 1. 网络嗅探器蓝图的输入
<appproject="NetworkSniffer">
<sniffername="sampler"sample_probability=".7">
<logFilename="packet_types"/>
<packettype="TCP"subType="SYN">
<logToFilename="packet_types"/>
<findResponsetype="TCP"subType="ACK"timeout="1"/>
</packet>
<packettype="UDP">
<logToFilename="packet_types"/>
</packet>
</sniffer>
</app>
蓝图将转换这些输入参数为实现该网络嗅探器的代码。蓝图的参数可视为自定义编程语言,而蓝图扮演 “编译器” 的角色,将输入转换为本机工件。
2. 控制文件
这些文件控制代码生成的执行。控制标记中最重要的标记是 <ws:file>,它将执行一个模板并将结果转储至指定的文件。代码生成执行从 main.jet 开始,这与程序的 main 函数类似。
3. 模板文件
模板文件指定如何以及何种情况下生成文本。该文本可以是代码、配置文件或其他。

更多有关 XPath 的信息

如果 XPath 对于您是个陌生概念,请查看 XPath 参考资料

XPath

既然任何 JET 蓝图的输入都是一个 XML 模型,XPath 语言被用来引用节点和属性。此外,在表达式里 XPath 有自己的参数使用方式,这在 JET 里使用得非常多。要点如下:

  1. 路径表达式 与文件系统路径相似。路径是由斜杠分开的一系列步(/)。
  2. 从左向右估算步,如果这样做,通常会下行模型树。
  3. 每步通过其名字定义树节点(尽管存在其他可能性)。
  4. 在步的结尾,步可以在方括号([])中编写可选的过滤器条件。
  5. 初始斜杠(/)指示表达式开始于模型树的根。
  6. 路径表达式还可以以变量开始,变量是以美元符号($)开头的名字。

关于 JET 中的 XPath ,应记住以下几个要点:

  1. 变量是由几个 JET 标记定义的 - 注意 var 属性。它们可能也是由 c:setVariable 标签定义的。
  2. 需要路径表达式的 JET 标签有一个 select 属性。
  3. 任何标签属性都可能包含一个动态的 XPath 表达式,是由括号({})所包含的 XPath 表达式。

JET 标签

下例将使用下列输入模型。


清单 2. 输入模型

<appmiddle="Hello">
<personname="Chris"gender="Male"/>
<personname="Nick"gender="Male"/>
<personname="Lee"gender="Male"/>
<personname="Yasmary"gender="Female"/>
</app>
ws:file
该标签属于蓝图的 control 部分,它初始化一个模板。例如:
<ws:filetemplate="templates/house.java.jet"
path
="{$org.eclipse.jet.resource.project.name}/house1.java">
将在输入模型上运行 house.java.jet 模板并将结果转储在 $(Project Root)/house1.java 中。{$org.eclipse.jet.resource.project.name} 是一个动态 XPath 表达式,用 org.eclipse.jet.resource.project.name 变量的值替换部分字符串。该变量是由 JET 引擎定义的。
c:get
该标签将输出 XPath 表达式的结果。例如,Pre<c:get select="/app/@middle" />Post 将输出 PreHelloPost。注意 select 参数将使用 XPath 表达式。要在期望静态字符串的参数中使用 XPath 表达式,可以通过将表达式封装在括号({})中来调用动态 XPath 表达式。
c:iterate

该标签将遍历具有特定名称的节点,为每个节点执行 iterate 的主体。例如:

<c:iterateselect="/app/person"var="currNode"delimiter=",">
Name=
<c:getselect="$currNode/@name"/>
</c:iterate>

将输出 Name = Chris, Name = Nick, Name = Lee, Name = Yasmary

iterate 标签通常也用于控制模板的其实标记。例如,如果要为模型中的每个人创建 Java™ 类,可使用如下代码:

<c:iterateselect="/app/person"var="currPerson">
<ws:filetemplate="templates/PersonClass.java.jet"
path
="{$org.eclipse.jet.resource.project.name}/{$currPerson/@name}.java"/>
</c:iterate>

这将创建四个 Java 类文件:Chris.java、Nick.java、Lee.java 和 Yasmary.java。注意启动标记 path 属性中的 {$currPerson/@name} 字符串。既然 path 参数不需要 XPath 表达式(像 select 参数一样),{...} 字符告知 JET 引擎通过计算 XPath 表达式代替这部分字符串。$currPerson/@name 告诉引擎用 currPerson 节点(是定义在 iterate 标签中的变量)的 name 属性来代替其字符串。

此外,在 PersonClass.java.jet 模板中,它可以引用定义在 iterate 标签中的 currPerson 节点变量。例如,假设 PersonClass.java.jet 如下所示:


清单 3. PersonClass.java.jet

class<c:getselect="$currPerson/@name"/>Person...{
publicStringgetName()...{
return"<c:getselect="$currPerson/@name"/>";
}

publicvoidshout()...{
System.out.println(
"Hello!!!");
}

}

Yasmary.java 的形式将如下:


清单 4. Yasmary.java

classYasmaryPerson...{
publicStringgetName()...{
return"Yasmary";
}

publicvoidshout()...{
System.out.println(
"Hello!!!");
}

}

Lee.java 的形式如下:


清单 5. Lee.java

classLeePerson...{
publicStringgetName()...{
return"Lee";
}

publicvoidshout()...{
System.out.println(
"Hello!!!");
}

}
c:choosec:when
这些标签允许模板根据值有条件地转储文本。例如,下列代码:

清单 6. c:choose/c:when 示例
<c:iterateselect="/app/person"var="p">
<c:chooseselect="$p/@gender">
<c:whentest="'Male'">Brother</c:when>
<c:whentest="'Female'">Sister</c:when>
</c:choose>
</c:iterate>

将输出:

Brother
Brother
Brother
Sister

注意 c:when 标签需要 test 参数,这需要一个 XPath 表达式。既然我们要通过一个常量比较 select 参数,可用单引号 ('') 包含常量。

c:set
该标签允许模板动态更改输入模型的属性。一个例子是:在一个字符串以多个方式映射输出文本时,像 Chris 可能映射到 ChrischrisChrisClassCHRIS_CONSTANT 等。c:set 将其内容设置为指定的属性。下面的例子为每个人存储名为 className 的属性并在名字之后简单添加词 Class

清单 7. c:set 例子
<c:iterateselect="/app/person"var="p">
<c:setselect="$p"name="className">
<c:getselect="$p/@name"/>Class</c:set>
</c:iterate>
setVariable
该标签允许模板声明和使用一个全局变量,使用 XPath 的全部能力来在任何时候操纵该变量。例如,假设要输出在输入模型中提供了多少个 person 节点。可以利用以下代码:

清单 8. c:setVariable 示例
<c:setVariableselect="0"var="i"/>
<c:iterateselect="/app/person"var="p">
<c:setVariableselect="$i+1"var="i"/>
</c:iterate>
Numberofpeople=
<c:getselect="$i"/>.

输出 Number of people = 4。

可以使用 get 输出变量,如上例所示。

有超过 45 个标签,这使输出文本具有强大的表现力。表现力大多源于存在条件逻辑、动态更改输入模型和控制执行流的标签。

扩展 JET

JET 是可扩展的通过使用 Eclipse 的扩展点机制。以下是 JET 提供的六个扩展点。

org.eclipse.jet.tagLibraries
该扩展点负责定义标记库。JET 已经包含四个标记库(控制、格式、工作空间、Java),如果您要添加自己的标签功能,可从这里入手。
org.eclipse.jet.xpathFunctions
这允许在 JET XPath 执行时启用自定义 XPath 表达式。一个 JET 中这样的例子是:通过扩展该扩展点,在 XPath 表达式中使用 camelcase(参见 JET 源代码中的 CamelCaseFunction)。
org.eclipse.jet.transform
用于声明您的插件在提供 JET 转换。这是更改您使用什么来启动模板(取代 main.jet)的位置。
org.eclipse.jet.modelInspectors
这允许您定义检查器,使得 JET XPath 引擎来将加载的 Java 对象解释为 XPath 节点。检查器是将对象适配为 XPath 信息模型。作为例子,JET 使用一个模型来浏览 Eclipse 工作空间。注意这是临时 API,并可能随时间而发生变化。
org.eclipse.jet.modelLoaders
这允许您定义 JET 转换和从文件系统加载的 JET <c:load> 标签以怎样的方式使用模型。作为示例,JET 提供模型加载器 loader org.eclipse.jet.resource,将加载 Eclipse IResource(文件,文件夹或项目)并允许通过该资源导航 Eclipse 工作空间。
org.eclipse.jet.deployTransforms
这允许您来将一个 JET 转换打包为一个用于简单发行的插件(包)。这可以被 UI 用来查看哪些转换可用。

实例:编写代码来生成代码

下列实例是一个模板,用于创建拥有任意数量属性的类。每个属性将有 getter 和 setter 与之关联,还有一些初始值。此外,所调用的函数的名称将输出到命令行,通过这种方式,模板即可为各函数添加简单的日志。


清单 9. 属性模板

class<c:getselect="/app/@class"/>{
<c:iterateselect="/app/property"var="p">
private
<c:getselect="$p/@type"/><c:getselect="$p/@name"/>;
</c:iterate>

public
<c:getselect="/app/@class"/>(){
<c:iterateselect="/app/property"var="p">
this.
<c:getselect="$p/@name"/>=<c:chooseselect="$p/@type">
<c:whentest="'String'">"<c:getselect="$p/@initial"/>"</c:when>
<c:otherwise><c:getselect="$p/@initial"/></c:otherwise>
</c:choose>
;
</c:iterate>
}

<c:iterateselect="/app/property"var="p">
publicvoidset
<c:getselect=
"camelCase($p/@name)"/>(<c:getselect="$p/@type"/>
<c:getselect="$p/@name"/>){
System.out.println
("Inset
<c:getselect=
"camelCase($p/@name)"/>()");
this.
<c:getselect="$p/@name"/>=<c:getselect="$p/@name"/>;
}

public
<c:getselect=
"$p/@type"/>get<c:getselect="camelCase($p/@name)"/>(){
System.out.println("Inget
<c:getselect="camelCase($p/@name)"/>()");
return
<c:getselect="$p/@name"/>;
}

</c:iterate>
}

这里是该模板的输入模型实例:


清单 10. 输入参数

<appclass="Car">
<propertyname="model"type="String"initial="HondaAccord"/>
<propertyname="horsepower"type="int"initial="140"/>
<propertyname="spareTires"type="boolean"initial="true"/>
</app>

这些输入参数生成如下类:


清单 11. 生成的类

classCar...{
privateStringmodel;
privateinthorsepower;
privatebooleanspareTires;

publicCar()...{
this.model="HondaAccord";
this.horsepower=140;
this.spareTires=true;
}


publicvoidsetModel(Stringmodel)...{
System.out.println(
"InsetModel()");
this.model=model;
}


publicStringgetModel()...{
System.out.println(
"IngetModel()");
returnmodel;
}


publicvoidsetHorsepower(inthorsepower)...{
System.out.println(
"InsetHorsepower()");
this.horsepower=horsepower;
}


publicintgetHorsepower()...{
System.out.println(
"IngetHorsepower()");
returnhorsepower;
}


publicvoidsetSparetires(booleanspareTires)...{
System.out.println(
"InsetSparetires()");
this.spareTires=spareTires;
}


publicbooleangetSparetires()...{
System.out.println(
"IngetSparetires()");
returnspareTires;
}


}

实例:编写处理代码

为强调 JET 不仅仅可用来生成代码,我们给出了下面这个实例,这是一个模板,生成具有不同语气的电子邮件消息。所生成的各电子邮件的目的是是向某人索要求各种东西。下面提供控制文件(main.jet)及其调用的模板(email.jet)。


清单 12. main.jet

<c:iterateselect="/app/email"var="currEmail">
<ws:filetemplate="templates/email.jet"
path
="{$org.eclipse.jet.resource.project.name}/{$currEmail/@to}.txt"/>
</c:iterate>

清单 13. email.jet

<c:setVariablevar="numItems"select="0"/>
<c:iterateselect="$currEmail/request"var="r">
<c:setVariablevar="numItems"select="$numItems+1"/>
</c:iterate>
<c:setselect="$currEmail"name="numItems"><c:getselect="$numItems"/></c:set>
<c:chooseselect="$currEmail/@mood">
<c:whentest="'happy'">Mydear</c:when>
<c:whentest="'neutral'">Dear</c:when>
<c:whentest="'angry'">Myenemy</c:when>
</c:choose><c:getselect="$currEmail/@to"/>,

Iamwritingyou
<c:chooseselect="$currEmail/@mood">
<c:whentest="'happy'">injoy</c:when>
<c:whentest="'neutral'"></c:when>
<c:whentest="'angry'">inburninganger</c:when>
</c:choose>toaskfor<c:chooseselect="$currEmail/@numItems">
<c:whentest="1">
a
<c:getselect="$currEmail/request/@item"/>.
</c:when>
<c:otherwise>
thefollowing:

<c:setVariablevar="i"select="0"/>
<c:iterateselect="$currEmail/request"var="r">
<c:setVariablevar="i"select="$i+1"/>
<c:getselect="$i"/>.<c:getselect="$r/@item"/>
</c:iterate>

</c:otherwise>
</c:choose>
<c:chooseselect="$currEmail/@mood">
<c:whentest="'happy'">Please</c:when>
<c:whentest="'neutral'">Please</c:when>
<c:whentest="'angry'">Eithersuffermywrath,or</c:when>
</c:choose>sendme<c:chooseselect="$currEmail/@numItems">
<c:whentest="1">
thisitem
</c:when>
<c:otherwise>
theseitems
</c:otherwise>
</c:choose><c:chooseselect="$currEmail/@mood">
<c:whentest="'happy'">atyourearliestconvenience.</c:when>
<c:whentest="'neutral'">promptly.</c:when>
<c:whentest="'angry'">immediately!</c:when>
</c:choose>

<c:chooseselect="$currEmail/@mood">
<c:whentest="'happy'">Yourfriend,</c:when>
<c:whentest="'neutral'">Sincerely,</c:when>
<c:whentest="'angry'">Inrage,</c:when>
</c:choose>

<c:getselect="/app/@from"/>

该模板的输入模型实例如下:


清单 14. sample.xml

<appfrom="Nathan">
<emailto="Chris"mood="angry">
<requestitem="well-writtenarticle"/>
</email>
<emailto="Nick"mood="happy">
<requestitem="Piano"/>
<requestitem="Lollipop"/>
<requestitem="BlankDVDs"/>
</email>
</app>

mood 电子邮件蓝图应用于这些参数,生成下列两个文件。


清单 15. Chris.txt

MyenemyChris,

Iamwritingyouinburningangertoask
forawell-writtenarticle.
Eithersuffermywrath
,orsendmethisitemimmediately!

Inrage
,
Nathan

清单 16. Nick.txt

MydearNick,

Iamwritingyouinjoytoask
forthefollowing:

1.Piano
2.Lollipop
3.BlankDVDs

Pleasesendmetheseitemsatyourearliestconvenience
.

Yourfriend
,
Nathan

结束语

在结束之前,我们希望感谢 Paul Elder 提供了宝贵的意见。整体上来说,JET 的用途不仅限于简化代码生成。JET 是一个新的 Eclipse 技术项目,我们期待有更多的开发人员在工作中使用它。



参考资料

学习

分享到:
评论

相关推荐

    Eclipse 项目有一个称为 JET 的技术项目就是一个专门的代码生成器

    包含了下面文章的例子:使用 JET 在 Eclipse 中创建更多更好的代码(http://www.ibm.com/developerworks/cn/opensource/os-ecl-jet/)

    Eclipse_EMF_JET_自动代码生成技术入门

    Eclipse_EMF_JET_自动代码生成技术入门

    eclipse.jet resource

    eclipse jet 的源码,很不错的

    用模型驱动Eclipse开发

    EMF(EclipseModelingFramework)是一个模型架构和代码生成工具,它可以用来建构以结构化数据为基础的工具或者应用。作为MDA和Eclipse的结合体,它发展迅速,IBM的大部分工具产品如RSA等都将建立在它的基础之上。...

    springboot整合jetcache完整代码

    springboot整合jetcache完整代码,包括本地缓存、redis缓存,以及多缓存同时使用

    自己动手写开发工具--基于Eclipse的工具开发

    本书系统地介绍了SWT、Draw2D、GEF、JET等与Eclipse插件开发相关的基础知识,并且以实际的开发案例来演示这些知识的实战性应用,通过对这些实际开发案例的学习,读者可以非常轻松地掌握Eclipse插件开发的技能,从而...

    Jet的脚手架工具帮助您更便捷地使用Jet

    Jet 的脚手架工具,帮助您更便捷地使用Jet

    一个开源的Eclipse rcp 项目Dengues

    该项目基于Eclipse plug-ins技术,充分运用SWT/JFace/OSGI/EMF/GMF/GEF/JET等ECLIPSE核心技术进行开发,力图实现数据库的ETL功能,并为ECLIPSE开发技术的普及和推广贡献出自己的一份力量。该项目代码简练、实用,将...

    打印机驱动 HP M202DW驱动

    打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机驱动 HP M202DW驱动打印机...

    三菱MR-JET-G手册资料.rar

    MR-JET-G 用户手册 (导入篇) MR-JET 用户手册 (硬件篇) MR-JET 合作商编码器用户手册 MR-JET 用户手册 (功能篇) MR-JET-G 用户手册 (通信功能篇) MR-JET 用户手册 (调整篇) MR-JET 用户手册 (故障排除篇) MR-JET-G ...

    JET51A 用户指南

    ET51A 可以通过 JTAG 接口对中颖的增强型 8051 内核的系列单片机实现仿真以 及下载

    JET Tutorial(代码生成教程)

    EMF工程包含两个强劲的代码生成工具:JET (Java Emitter Templates)和JMerge (Java Merge),使用JET你可以使用类似JSP的语法(实际上是JSP语法的子集)很容易的去编写模板来描述你想要生成的代码.

    EasyMda:一个Eclipse插件,可从基于Java的模型生成源代码-开源

    easyMda是一个Eclipse插件,可以从基于Java类的模型生成源代码。 这个项目的主要目标是提供:最灵活(可以想象的任何东西,可以建模和生成),最容易开发和使用,并且非常快速:MDA /代码生成器工具。 与其他Mda工具...

    打印机驱动 惠普HP Color LaserJet Pro M452dn 驱动

    打印机驱动 惠普HP Color LaserJet Pro M452dn 驱动打印机驱动 惠普HP Color LaserJet Pro M452dn 驱动打印机驱动 惠普HP Color LaserJet Pro M452dn 驱动打印机驱动 惠普HP Color LaserJet Pro M452dn 驱动打印机...

    打印机驱动 惠普HP LaserJet Pro MFP M128fp 驱动

    打印机驱动 惠普HP LaserJet Pro MFP M128fp 驱动打印机驱动 惠普HP LaserJet Pro MFP M128fp 驱动打印机驱动 惠普HP LaserJet Pro MFP M128fp 驱动打印机驱动 惠普HP LaserJet Pro MFP M128fp 驱动打印机驱动 惠普...

    T-SQL JET-SQL 参考手册

    随着 Microsoft Jet 4.X 版的发行,可以看出 Microsoft OLE DB Provider for Jet 使用了更多的 ANSI-92 SQL 语法。相反地,在 ANSI SQL 中也不支持 Microsoft Jet SQL 所包含的某些保留字和性能。

    吉星JET-DBG028高拍仪驱动 官方版

    吉星JET-DBG028高拍仪驱动是配套JET-DBG028产品设备使用的驱动软件。用户可以使用吉星打印机的时候可能会遇到不能正常启动高拍仪设备的问题,这是因为您的电脑上缺少了相对应的驱动程序。下载安装就可以解决啦。产品...

    通过创建JRO.JetEngine对象实现压缩Access数据库

    资源介绍:。源码通过创建JRO.JetEngine对象实现压缩Access数据库。资源作者:。易语言教程。资源界面:。资源下载:。

    Jet标签自动生成代码

    NULL 博文链接:https://long316.iteye.com/blog/1734638

Global site tag (gtag.js) - Google Analytics