??xml version="1.0" encoding="utf-8" standalone="yes"?> 在我们创建领域模型前Q我们有必要了解一下我们的模型用来表达什么内宏V?所以我先解释一下在q个pd文章中要实现应用?假设Eclipsel织邀请你~写一个让他们理贡献者和目的应用程序?
我们需要创Z个模型来表达客户提供的信息。他们有可能如下图? 让我们进一步的看看q个模型? fundation是这个模型的根,他拥有两个列表属性? Eclipse目拥有很多属性,比如目开始和l束旉、项目的主页的url{等。下面列出我们最感兴的? 当一个用hZ个项目的贡献者(CommitterQ时Q这徏立了一个committership。他拥有一个开始时间和l束旉。另外我们还要记录下下面的属性?
贡献者或目领导人的信息。我们关pȝ信息如下Q? 下面q张cdl出了关于上面模型的全貌? 正如你所看到的,我把许多关系设成了双向关pR?As you noticed I modeled many of the relations as
bidirectional relations.
q个q不是严D求所有地斚w要这P因ؓ有的地方可以通过eComtainer来获取他的父二Ӏ就像project-subproject一栗?
但是包含关系Qcontainment
relationshipQ在使用databinding的情况下׃太合适了。因Z子到父亲时没有对应featureQ只能通过调用eContainer()Ҏ(gu)来获得?
EMF提供了一个编辑器来创Z的Ecore-Modelq把它保存成XMI格式。我们可以用它来创徏试数据。下囑ְ是一个例子?/p>
在学习EMF-Databinding的时候发CTom Schindl的博客。他的博客中有一个关于EMF
Databinding的专题。感觉很不多。想试着译一下?那么Tom
Schindl是何思h也?他是JFace目的一个ContributorQ在2007q?a target="_top">Eclipse
Zone
曾l采访过他?所以称他ؓEMF Databinding的专家一点也不过分? 原文\径ؓhttp://tomsondev.bestsolution.at/2009/06/06/galileo-improved-emf-databinding-support/
我很高兴的宣布在Eclipse-Galileo中EMF-2.5已经开始支持新的Eclipse-Databinding API了。荣誉归Matthew
HallQ他审查我的代码Q帮我整理支撑部分ƈ且整理文档(详细内容?a target="_top">bug
262160
中) 几周前我成ؓ了EMF目的捐献者,现在我负责Databinding对EMF的支持模块。我尽力修正API中的问题Q回{Newsgroup中的问题?
请允许我在介l这个API的优点以及如何用它之前声明一点:q个APIq处于过渡期Q他可能会有一些细微的变化。不q我们将会详l说明变化的部分? 我将用一个系列文章来展现q个新的EMF-Databinding: Z让你快速进入EMF-Databinding中,我在前几天做了一个例子? 所有代码都是基于EPL协议Q你可以在从Eclipse-CVS
处获得?
现在只是看了
在项目中单的使用了一下他作ؓ查询的工兗感觉他真的很不错,在下一D|间将会重点去了解他?/p>
projects:
像EMF,Techonlogy,Platformq样的顶U项目?
persons:
参加一个或多个目的h?
subprojects:
一个项目可以拥有多个子目。子目本n也可以拥有多个子目?
parent:
目有一个父Ԍ除了目外)。这意味着目和子目Qproject-subprojectQ的关系是一个双向的关系?
projectleads
一个项目有多个目领导人?
committers
一个项目可以拥有多个A献者?
project:
和committership相关的项目。项目和committership是一个双向的关系?
person:
参加目的h?
committerships:
用于保存和h相关的所有的committerships.q说明h和committership是一个双向关pR?
]]>
Note
2. 原文
W一部分Q?a target="_top">创徏领域模型
W二部分Q?a target="_top">介绍新的Properties API
W三部分Q?a target="_top">用EMF-Databindingl定到TreeViewer
W四部分Q?a target="_top">在master-detail模式中用Properties API
W五部分Q?a target="_top">用EMF-Databindingl定到TableViewer
W六部分QWrite your own Property for unsupport Widget-Types
W七部分QMake the storage system plugable
]]>
Jmerger
使用初步
(
?/font>
)
前面一提C他基本的概念和能完成的功能。在q一里我们来看看他的用条件和使用Ҏ(gu)?/font>
使用条gQ应?/font>
org.eclipse.jdt.core
Q提供基本的语法分析Q?/font>
org.eclipse.core.runtime
Q提供基本的
URI
{)
org.eclipse.ui
Q提供进度条Q我qCq个。其他可能还有)?/font>
看到他要使用q么?/font>
Eclipse
的东ѝ我d的打消了?/font>
Eclipse
外用他的打(如果谁有好的解决Ҏ(gu)记得l我发一份。在下感Ȁ不尽Q?/font>
我们下面来看看如何定制他的合ƈ规则是如何定义的吧。我先做法是找了一个例子。看看他是如何工作的?/font>
我的
Merge.xml
如下Q?/font>
清单
2
Q?/font>
<? xml version = "1.0" encoding = "UTF-8" ?>
< merge:options xmlns:merge = "http://www.eclipse.org/org/eclipse/emf/codegen/jmerge/Options" >
< merge:dictionaryPattern
name = "generatedMember"
select = "Member/getComment"
match = "\s*@\s*(gen)erated\s*\n" />
<!-- if target is generated, transfer -->
<!-- change to sourceMarkup if the source is the standard -->
< merge:pull
targetMarkup = "^gen$"
sourceGet = "Method/getBody"
targetPut = "Method/setBody" />
</ merge:options >
q行前的
Source
Q?/font>
Java
Source A
Q?
?/font>
分源代码?/font>
/**
*
Source javadoc 13
*
<!-- begin-user-doc -->
*
Source user javadoc 14
*
<!-- end-user-doc -->
*
Source javadoc 15
*
@return source
*
@generated
*/
public
boolean isID()
{
//
begin-user-code
System.out.println("Source
user code 1");
//
end-user-code
System.out.println("Source
code 2");
return
id == "source";
}
q行?/font>
Target(Java
Source B)
部分的源代码为:
/**
* Source javadoc 13
* <!-- begin-user-doc -->
*
Target user javadoc 16
* Target user javadoc 17
* <!--
end-user-doc -->
* Source javadoc 15
* @return source
* @generated
*/
public boolean isID()
{
//This
is my owner code
System.out.print("Will be replace");
// begin-user-code
System.out.println("Target user
code 2");
// end-user-code
System.out.println("Source code 2");
return id ==
"source";
}
/**
* Target javadoc 19
* <!-- begin-user-doc -->
*
Target user javadoc 20
* Target user javadoc 21
* <!--
end-user-doc -->
* Target javadoc 22
* @param target
* @generated NOT
*/
public void setID(boolean value)
{
//This Jet Code
System.out.println("Not be
replaced!");
id = value ? "target" :
"source";
System.out.println("Target code
4");
}
注意Q?/font>
isID
Ҏ(gu)
注释里有?/font>
@generated?/font>
q一行。?
setID
Ҏ(gu)的注释中?/font>
@generated
NOT
?/font>
q行后的l果是(
Result
of merge
Qؓ
/**
* Source javadoc 13
* <!-- begin-user-doc -->
*
Target user javadoc 16
* Target user javadoc 17
* <!--
end-user-doc -->
* Source javadoc 15
* @return source
* @generated
*/
public boolean isID()
{
//
begin-user-code
System.out.println("Source
user code 1");
//
end-user-code
System.out.println("Source
code 2");
return
id == "source";
}
//
使用?/font>
Source
部分的代码?/font>
/**
* Target javadoc 19
* <!-- begin-user-doc -->
*
Target user javadoc 20
* Target user javadoc 21
* <!--
end-user-doc -->
* Target javadoc 22
* @param target
* @generated NOT
*/
public void setID(boolean value)
{
//This Jet Code
System.out.println("Not be
replaced!");
id = value ? "target" :
"source";
System.out.println("Target code
4");
}
//
l持原来
Target
中的代码没有变化?/font>
q样我们׃隄?/font>
<
merge:dictionaryPattern
…?>
D?/font>
是定义了一个匹配模式。具体的q个匚w模式要做的动作就是在
<
merge:pull
targetMarkup = "^gen$"
sourceGet = "Method/getBody"
targetPut = "Method/setBody" />
D中定义了。猜想他只是?/font> Source 部分的内容直接输出到 Target 那里M?/font>
如果我们觉得需要做点什么过滤。比如说想保?/font>
Target
中一个特定的内容。这一个我们可以通过
merge:pull
?/font>
sourceTransfer
属性来讄?/font>
现在来看一个例子:
?/font>
merge:pull
节点修改?/font>
<
merge:pull
targetMarkup = "^gen$"
sourceTransfer = "(\s*//\s*begin-user-code.*?//\s*end-user-code\s*)\n"
sourceGet = "Method/getBody"
targetPut = "Method/setBody" />
注意Q添加了一?
sourceTransfer,
他的?/font>
值是一个正则表辑ּ。匹配的是被
?font face="Courier New, monospace">//
begin-user-code?
和?/font>
//
end-user-code?/font>
包围住的所有的字符?/font>
Target
的代码ؓQ?span lang="zh-CN">我们现在只是x
isID
Ҏ(gu)
Q?/font>
?/font>
/**
* Source javadoc 13
* <!-- begin-user-doc -->
*
Target user javadoc 16
* Target user javadoc 17
* <!--
end-user-doc -->
* Source javadoc 15
* @return source
* @generated
*/
public boolean isID()
{
//
begin-user-code
System.out.println("Source
user code 1");
System.out.println("This
will not be replaced!");
//
end-user-code
System.out.print("this
will be replaced!");
System.out.println("Source
code 2");
return
id == "source";
}
h意看一下红色部分的两行代码?/font>
合ƈ后的代码为:
/**
* Source javadoc 13
* <!-- begin-user-doc -->
*
Target user javadoc 16
* Target user javadoc 17
* <!--
end-user-doc -->
* Source javadoc 15
* @return source
* @generated
*/
public boolean isID()
{
//
begin-user-code
System.out.println("Source
user code 1");
System.out.println("This will not be
replaced!");
//
end-user-code
System.out.println("Source code 2");
return
id == "source";
}
在?/font>
//
begin-user-code
?/font>
和?/font>
//
end-user-code
?/font>
外的代码全部被替换成了。这样就起到了过滤的效果?/font>
?/span>EMF框架中最l会Ҏ(gu)模型生成代码Q还可以反复生成。还能你自q辑的内容不丢失。够好玩的吧。那么这部分是怎么实现的呢Q看q一?/span>EMF介绍可以知?/span>EMF是通过JET完成代码生成的动作的。在?/span>使用 Eclipse Modeling Framework q行建模》这个系列的文章可以了解到q一炏V在该系列文章的W三部分q可以了解到使用JMerge 可以实现“成的代码插入现有的代码中,或者允总后的开发h员来定制所生成的代码,而不需要在重新生成代码旉新编写Q何内宏V”这L功能?/span>
他是通过创徏Junit 试cM例子的。他说过的东西我׃啰嗦了。我只是把我个h在看了他文章后的一些东西整理一下?/p>
好,现在q入正题?/p>
首先我们来说一?font face="Times New Roman, serif">JMergeq个名字?font face="Times New Roman, serif">Mergeq个单词是合q的意思。前面加了一个?font face="Times New Roman, serif">J?/font>不用多说Q肯定表C?font face="Times New Roman, serif">Java了(完全是参?font face="Times New Roman, serif">Junit,log4j…?/font>Q。那么我大?
猜测q个工具是用来合q?font face="Times New Roman, serif">Java代码的。既然是合ƈ应该符合下图描q的动作?img src="http://www.aygfsteel.com/images/blogjava_net/jetgeng/Jmerge-Name.jpg" alt="Jmerge-Name.jpg" border="0" height="227" width="488" />
合ƈ肯定是把两个东西和成一个。所以图中的Java Source A ?font face="Times New Roman, serif">Java Source B分别代表需要合q的部分了。最后的Result of Merge是合ƈ后的那一个结果了。应为我们合q的?font face="Times New Roman, serif">Java代码。这些代码如何合qӞ也就是我们期望的合ƈl果是什么样的。图中的Rule of merge是代表的这部分信息?/p>
在下面?font face="Times New Roman, serif">Jmerge的代码中
清单 1.
调用 JMerge
2 JMerger merger = getJMerger();
3
4 // set source
5 merger.setSourceCompilationUnit(
6 merger.createCompilationUnitForContents(generated));
7
8 // set target
9 merger.setTargetCompilationUnit(
10 merger.createCompilationUnitForInputStream(
11 new FileInputStream(target.getLocation().toFile())));
12
13 // merge source and target
14 merger.merge();
15
16 // extract merged contents
17 InputStream mergedContents = new ByteArrayInputStream(
18 merger.getTargetCompilationUnit().getContents().getBytes());
19
20 // overwrite the target with the merged contents
21 target.setContents(mergedContents, true, false, monitor);
22 //
23
24 //
25 private JMerger getJMerger() {
26 // build URI for merge document
27 String uri =
28 Platform.getPlugin(PLUGIN_ID).getDescriptor().getInstallURL().toString();
29 uri += "templates/merge.xml";
30
31 JMerger jmerger = new JMerger();
32 JControlModel controlModel = new JControlModel( uri );
33 jmerger.setControlModel( controlModel );
34 return jmerger;
35 }
我们可以很容易的扑և它们的对应物?/p>
我们先从JMerger的创建开始看起吧?/p>
uri += "templates/merge.xml";
JMerger jmerger = new JMerger();
JControlModel controlModel = new JControlModel( uri );
jmerger.setControlModel( controlModel );
q里用一个名ZؓZؓ?/span>merge.xml
的文件作ZؓZؓ输输?/span>input
参数创创H新Z一?/span>JControlModel
对象。传?/span>
传给JMerger
对象。做完这些后又调调用?
setSourceCompilationUnit
?
setTargetCompilationUnit
Ҏ(gu)。他们们?/span>
们的cȝ
cd都是IDOMCompilationUnit
Q用
q的朋友都会知道他就代表了一?/span>Java
文g
Q。很荣荣Ҏ(gu)׃惌v他们
们肯定就?/span>Java
Source A
?/span>Java
Source B
了至?/span>Rule
of merge
可以通过
q调?/span>
merger.merge()
后的
getContents
Q)Ҏ(gu)?/span>
?/span>获得
除了q种调用
方式外还有一个更
?/span>
的调用方式:
String
contents = merger.execute(null, new String[] { mergeXML,
source,target });
看了
execute
实现后就
不难
发现他的q?/span>
是用的W一
U?br />
关于具体如何定制合ƈ规则
和用条件打在下一中写?br />
共有三个部:
1. ~辑器的M。包括六U呈现方式?/SPAN>
a) Selection.
b) Parent.
c) List.
d) Tree
e) Table
f) Tree With Columns.
2. Outline部分?/SPAN>
Properties,会根据选择不同的对象而改变显C的内容?/SPAN>关于Jface部分的工作模式我在?/SPAN>Table View 的合作类的模式》一文中有提刎ͼ不过需要说明的是,?/SPAN>Jface中的Viewer他们?/SPAN>ContentProvider可能不一L?/SPAN>
要完成这部分的功?/SPAN>emf的生代码中分别攑ֈ了两个插仉实现了他们分别是edit?/SPAN>editor?/SPAN>
Edit提供?/SPAN>Item ?/SPAN>ProviderQ他存在的意义就在于把逻辑对象?/SPAN>UI分割开。?/SPAN>Editor通过使用edit提供?/SPAN>Provider实现了一个编辑器?/SPAN>UI?/SPAN>Command部分Q他是正真的用户界面部分?/SPAN>
下面我们先来看?/SPAN>edit中的cR?/SPAN>
好了Q首?/SPAN>edit中用的?/SPAN>adapt模型。所?/SPAN>edit中的插g对象会实现所有的viewer,Properties所需要的接口?/SPAN>
Emf为我们实现通用的接口。所以这l对是一个学习的好机会?/SPAN>
废话不多说了Q来看代码把?/SPAN>
首先看声明:
他们之间的职能以及实现的接口可用下图来描qͼ
ItemProviderAdapter完成一些基本功能。下面就分别从不同的接口来说?/SPAN>
1. ResourceLocator:该接口是用来q行资源定位的?/SPAN>
2. IDisposable ?/SPAN>emf框架提供的一U析构接口?/SPAN>
3. IChangeNotifier ?Notification and Adapters"模式提供必需的方法?/SPAN>
CreateChildCommand.Helper
最下面?/SPAN>EMFҎ(gu)我们的模型生的Provider的了。他实现?/SPAN>5个接口?/SPAN>
1. IEditingDomainItemProvider
q部分我q清楚,怀疑和command有关?/SPAN>
2. IStructuredItemContentProvider
该接口ؓTableViewer,ListViewer,TreeViewer提供服务?/SPAN>
This is the interface needed to populate the top level items in a TreeViewer, the items of a ListViewer, or the rows of a TableViewer.
3. ITreeItemContentProvider
This is the interface needed to populate subtrees in a TreeViewer
4. IItemLabelProvider
This is the interface implemented to provide a label text and even a label icon for an item;
it receives delegated calls from ILabelProvider.
5. IItemPropertySource
This is the interface is needed to populate property sheet items?/SPAN>it is the same as IpropertySource?/SPAN>except that the object is passed as the first parameter for each method.q一还只是edit部分刚开一个头?/SPAN>
下一期会介绍一下他的command部分?BR>
代码生成后,我就想看?/span>EMF为我生成了什么样的代码。我如果需要修改的话该如何修改?/span>
我的?/span>Hellow world”是采用的?/span>Using EMF”文中的模型?br>从图中我们可以看到有三个包:
他们分别是:family,family.impl?/span>family.util?/span>
family?/span>family.impl包之间的差别是一个是InterfaceQ另外一个是q些Interface的实现?/span>
我们先来看看我们模型中出现过的类Q?/span>
Family,FamilyTree,Female,Male以及Individual?/span>
׃我是采用Annotated Java的方式生成的模型。所以在family包中的代码ƈ没有太多的变化?br>他只是ؓ我提供了SetҎ(gu)。接口的l承也没有做修改。但是他对应的实现类有了很多变化?/span>
首先从类的申明来看:
q里有一张图可以清晰的说明这个承关pȝ职能?/span>
q样我们的就可以不写一行代码就可以使我们的对象hNotification/Common的功能(关于Notification?/span>Common的功能到底是怎样的,我会在后l的学习W记中记下来。呵呵,是不是很爽啊Q。另外在?/span>Eclipse Modeling Framework: A Developer's Guide》一书的W二章也有提到这部分的内?/span>,不过׃他讲解的EMF的版本比较老和我现在用的版本有点出入Q不q基本的功能q是讲到了?/span>
好了Q看完申明我们就来l往下看吧?br>?/span>Family下面有三个属性,father,mother?/span>children?/span>
EMFl我们生成的对应的代码ؓQ?/span>
以及一?/span>get?/span>setҎ(gu)?/span>
对于setҎ(gu)中除了基本的赋g外还加上了向所有对q次变动感兴观察者发送一个变更消息:
Male oldFather = father;
father = newFather;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, FamilyPackage.FAMILY__FATHER, oldFather, father));
}
对于getҎ(gu)要分基本cdq是对象q两U类型来处理?/span>
如果是基本类型,直接q回好了?/span>
如:
1?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">
Using EMF, Author :Catherine Griffin2?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">
EMF介绍pdQ二、从模型生成应用E序Q?/span> Author:八进?/span>3?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">
Mastering Eclipse Modeling FrameworkQ?/span>Author:Vladimir Bacvanski(Vladimir@inferdata.com) Petter Graff(petter@inferdata.com) Eclipse Modeling Framework: A Developer's Guide Author:Frank Budinsky, David Steinberg, Ed Merks, Raymond Ellersick, Timothy J. Grose