邋遢居

我的Java天堂

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  61 Posts :: 2 Stories :: 90 Comments :: 0 Trackbacks

#

Jmerger 使用初步 ( )

前面一篇提到了他基本的概念和能完成的功能。在这一篇里我们来看看他的使用条件和使用方法。

使用条件:应为

org.eclipse.jdt.core (提供基本的语法分析)

org.eclipse.core.runtime (提供基本的 URI 等)

org.eclipse.ui (提供进度条,我就看到了这个。其他可能还有)。

看到他要使用这么多 Eclipse 的东西。我彻底的打消了在 Eclipse 外使用他的打算(如果谁有好的解决方案记得给我发一份。在下感激不尽)。


我们下面就来看看如何定制他的合并规则是如何定义的吧。我先做法是找了一个例子。看看他是如何工作的。


我的 Merge.xml 如下:

清单 2

<? 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 >


运行前的 Source Java Source A 分源代码为

/**

* 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";

}








运行前 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");
}

注意: isID 方法 注释里有” @generated” 这一行。而 setID 方法的注释中是 @generated NOT


运行后的结果是( Result of merge )为

/**
* 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";

}

// 使用了 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");
}

// 维持原来 Target 中的代码没有变化。

这样我们就不难看出

< merge:dictionaryPattern ……/> 是定义了一个匹配模式。具体的这个匹配模式要做的动作就是在

< merge:pull

targetMarkup = "^gen$"

sourceGet = "Method/getBody"

targetPut = "Method/setBody" />

段中定义了。猜想他只是把 Source 部分的内容直接输出到 Target 那里去了。

如果我们觉得需要做点什么过滤。比如说想保留 Target 中一个特定的内容。这一个我们可以通过 merge:pull sourceTransfer 属性来设置。


现在来看一个例子:

merge:pull 节点修改成

< merge:pull

targetMarkup = "^gen$"

sourceTransfer = "(\s*//\s*begin-user-code.*?//\s*end-user-code\s*)\n"

sourceGet = "Method/getBody"

targetPut = "Method/setBody" />

注意:添加了一个 sourceTransfer, 他的值 值是一个正则表达式。匹配的是被

// begin-user-code” 和“ // end-user-code” 包围住的所有的字符。

Target 的代码为我们现在只是关注 isID 方法


/**
* 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";

}


请注意看一下红色部分的两行代码。

合并后的代码为:

/**
* 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";

}


在“ // begin-user-code 和“ // end-user-code 外的代码全部被替换成了。这样就起到了过滤的效果。

posted @ 2006-05-02 11:34 Jet Geng 阅读(1990) | 评论 (1)编辑 收藏

今天使用xml editor 发现一个问题。Snap1.jpg

如上图:我的目的是想注释掉节点merge:pull。于是在13的位置分别加上了注释的开始和关闭的tag。但是却发现了一个奇怪的问题。他认为注释到位置2就结束了。而位置2的”-->”是作为一个用引号“引”起来的值存在的啊。我迷糊了。

我使用的版本是Eclipse 3.2M3
version.jpg



posted @ 2006-05-02 08:24 Jet Geng 阅读(557) | 评论 (1)编辑 收藏

Jmerge的使用初步(一)

EMF框架中最终会根据模型生成代码,还可以反复生成。还能使你自己编辑的内容不丢失。够好玩的吧。那么这部分是怎么实现的呢?看过一点EMF介绍就可以知道EMF是通过JET完成代码生成的动作的。在《使用 Eclipse Modeling Framework 进行建模》这个系列的文章就可以了解到这一点。在该系列文章的第三部分还可以了解到使用JMerge 可以实现“成的代码插入现有的代码中,或者允许以后的开发人员来定制所生成的代码,而不需要在重新生成代码时重新编写任何内容。”这样的功能。

他是通过创建Junit 测试类作例子的。他说过的东西我就不啰嗦了。我只是把我个人在看了他文章后的一些东西整理一下。

好,现在进入正题。

首先我们来说一说JMerge这个名字。Merge这个单词是合并的意思。前面加了一个“J”不用多说,肯定表示Java了(完全是参考Junit,log4j……)。那么我就大胆 猜测这个工具是用来合并Java代码的。既然是合并就应该符合下图描述的动作。Jmerge-Name.jpg

合并肯定是把两个东西和成一个。所以图中的Java Source A Java Source B就分别代表需要合并的部分了。最后的Result of Merge就是合并后的那一个结果了。应为我们合并的是Java代码。这些代码如何合并,也就是我们期望的合并结果是什么样的。图中的Rule of merge就是代表的这部分信息。


在下面使用Jmerge的代码中

清单 1. 调用 JMerge

 1   // 
 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, truefalse, 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 }

我们可以很容易的找出它们的对应物。

我们先从JMerger的创建开始看起吧。

uri += "templates/merge.xml";

        JMerger jmerger = new JMerger();
JControlModel controlModel = new JControlModel( uri );
jmerger.setControlModel( controlModel );

这里用一个名为为为为叫merge.xml的文件作为为为为输输输input参数创创窜新建了一个JControlModel对象。传传传给JMerger对象。做完这些后又调调用了 setSourceCompilationUnit setTargetCompilationUnit 方法。他们们们们的类类类型都是IDOMCompilationUnit(用过的朋友都会知道他就代表了一个Java文件)。很荣荣容易就会想起他们们肯定就是Java Source A Java Source B了至于Rule of merge可以通过过调用merger.merge()后的getContents()方法获获得


除了这种调用方式外还有一个更简单的调用方式:

String contents = merger.execute(null, new String[] { mergeXML, source,target });


看了 execute 实现后就不难发现他的还是使用的第一种。

关于具体如何定制合并规则和使用条件打算在下一篇中写。



posted @ 2006-05-01 08:01 Jet Geng 阅读(2517) | 评论 (0)编辑 收藏

快要离开长三角了。心里多多少少有点空空的。
想想刚毕业初,和杨,刘,黄一起来到ks。日子虽说有点苦,但是大家相互鼓励着。也算挺happy。后来小熊又来到了昆山。一起炒饭,一起吃排挡。md还一起来sz。不过小熊在这里经历了一些事情后又回家了。现在想想他应该还挺happy吧。整天有父母疼着。
大熊那个笨蛋没多久也来ks了。想想他那么大块头和我分一点点炒蛋吃就好笑(那时候我们也买的起鸡蛋的)。游魂小晶,来了又走,走了又来。漂浮不定。他在sz的日子里给我真的不少帮助。
到这个时候就该说到福建夫妇了。毕业后第一次见他们是在ks的要得火锅店。长时间的热抱后坐下来狂吃狂喝。大家都差不多醉了,就黄还算清醒,算那丫的倒霉,就他卖单了。呵呵。
唐,班里的交际花。现在也快嫁人了。就在sz。想想以后回来可以直接杀到他们家挺不错。住旅店的钱都省了。
回头算算,在长三角和曾经在长三角打拼的兄弟姐妹有:
刘夫妇,黄夫妇,杨,小熊,大熊,福建夫妇,唐,徐,小晶,lv,八一,菠菜最后还有apple。
祝福兄弟姐妹们心想事成。呵呵,土了。
好了,不扯这么多了。说出来就得了。大家都在为自己的理想拼。我当然也不能落后啊。嗯,好好的祝福我在新的起点会有新的起色。
posted @ 2006-04-08 17:06 Jet Geng 阅读(565) | 评论 (0)编辑 收藏

                                 在eclipse rcp中使用spring框架

很久就想了如何在Rcp程序中使用Spring。让Spring容器来管理我们rcp程序中的Beans。看到web项目中使用了spring后带来的好处(最直接的就是看到代码量少了)就一脸的憧憬。想我的好日子什么时候才会来啊。

有这个憧憬后我就开始考虑改如何做了。大家肯定都知道如果在eclipse rcp程序中使用直接使用springbeanfactory无论你是使用方式都会说找不到配置文件的。这个其中的原因是Eclipse 的每个插件都使用他们自己的类加载器(class load

说明:eclipse中类的详细的装载过程可以产考《Contributing to eclipse 中文版》p44

所以说能够正确的找到bean的配置文件成了一个难题。

还有一个问题就是如何管理BeanFactory也是一个问题。

既然提出了这两个问题,那就的一个一个的面对啊。

第一个问题的解决方式。只要通过一个插件中的类就可以获得。

我试了一下通过如下代码可以切换class load

最头疼的问题就是如何来管理springBeanFactory。如果在每个Plugin类的继承类里都加上对beanfactory的创建。想想都是很恶心的事情。就为这个事情一直停滞不前。搞的我快郁闷死掉了。

就在快死还没有死的时候看到了一个叫EclipseSpring项目(http://sourceforge.net/projects/eclipse-spring/)。一看超爽。他直接把我想做的事情直接给做了。

下面我们就来看看一下他的发布包里代的那个例子。这个例子很简单。就只是提供了一个viewView里显示一个条问候语。
simple view.jpg

呵呵,是不是很界面太简单了。这个我们就不说了。我们来说说他这个示例中到底是怎么实现的。

先看看他的plugin.xml文件把。

pluginxml.jpg

看看那个org.eclipse.ui.view那个扩展点。是不是有点奇怪啊。他的类是net.sourceforge.eclipsespring.SpringExtensionFactory:example/userNameView这个样子的。一言看上去就不是一个类。而是一个类代了点参数。

不过可以断定他就是上图显示的view了。

在看看上面那个扩展点

<extension

         point="net.sourceforge.eclipsespring.beanFactoryContributors">

      <beanFactoryContributor

            class="net.sourceforge.eclipsespring.example.spring.BeanFactoryContributor"

            id="example"/>

   </extension>

这个扩展点干吗用的啊。嗯是一个问题。

插件文件下面除了一个plugin.xml文件外。还有一个bean.xml的文件。
springdiagram.jpg

这下一看,明白了她就一个spring需要的配置文件。并包括了对view的申明。

net.sourceforge.eclipsespring.beanFactoryContributors这个名字可以看出他是对beanFactory做了一个扩展。

去这个类看一下,是怎么回事。

只是发现了
getresource.jpg
一看可以知道。它在这里初始化了spring的配置文件。
这个插件项目的整个类图为
classes.jpg

稍微回顾一下。在一个plugin中要有BeanFactoryContributorspring配置文件合上net.sourceforge.eclipsespring插件就可以使用spring了。

关于在这个过程中beanFactory如何创建,和扩展点如何被调用。我会在下一篇里说明。今天想睡了,虽然有点早。呵呵
posted @ 2006-03-23 22:18 Jet Geng 阅读(3976) | 评论 (0)编辑 收藏

今天终于找到了在eclipse rcp中使用spring的方法。呵呵。应该好好的高兴一下。如果明天不去上海的话就做个例子出来。
先记下了。
这是必须要做好的事情。
posted @ 2006-03-17 22:54 Jet Geng 阅读(588) | 评论 (0)编辑 收藏

Ship Manager的界面
――我的第一个RCP程序

前一段时间说画出把给朋友做的程序ui画出来的。一直拖到现在。真是有点不好意思。好了闲话就不说了。

下图就是我做出来的界面。现在看起来还很粗糙。
mainui.jpg

这个程序主要任务就是维护一些船只的资料。然后能够迅速的查询出这些资料。这样就会出现了维护和查询这两大块。根据这样的情况设计出了上图的界面。

上图的界面包括三个部分:

l         功能导航(一个View)。呵呵,很基本的一个功能导航。

l         船舶搜索(一个View)。提供船舶查询功能。

l         船舶维护(一个Editors)。用于添加和修改船舶信息。

这里布局部分在createInitialLayout中完成的。

这个在前几天的blog中就可以找到代码。

不过有一点还是要提一下就是IfolderLayout中的createFolder方法中的各个参数。

public void addView(String viewId,
                    int relationship,
                    float ratio,
                    String refId)

refId - the id of the reference part; either a view id, a folder id, or the special editor area id returned by getEditorArea

最后一个参数表示我们添加的那个View相对于part的id。

如果我的代码是:
//add navigate view
        IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.3f, editorArea);
        left.addView(View.ID);
        
        
//Add Search part
        IFolderLayout button = layout.createFolder("button", IPageLayout.BOTTOM, 0.6f"left");
        button.addView(SearchView.ID);
效果会是
left.jpg
如果代码写成
//Add Search part
        IFolderLayout button = layout.createFolder("button", IPageLayout.BOTTOM, 0.6f, editorArea);

效果会成为:
button.jpg

呵呵,大家不要见笑。我刚开始学,这部分的内容。

还有就是找了一个DatePicker控件

http://sourceforge.net/projects/swt-datepicker 这个控件使用起来挺容易的。只要一句话就可以了。
DatePickerCombo datePick = new DatePickerCombo(shell,SWT.BORDER | SWT.READ_ONLY);

他默认的日期格式是DateFormat.SHORT.如果你不想使用这个日期格式你只要调用一下setFormat方法就好了。
datePick.setFormat(new SimpleDateFormat("yyyy-MM-dd"));

呵呵,个人还是比较喜欢"yyyy-MM-dd"。不过我建议不要像我这么写。最好能够在整个项目中统一一个地方来创建SimpleDateFormat。如:
comboBuildDate.setFormat(SystemConfig.getDateFormat());



这样,整个项目就可以保证有一个统一的日期格式。更要紧的是如果以后有修改日期格式的需求的时候只要修改一处就好了。



posted @ 2006-03-12 09:19 Jet Geng 阅读(2885) | 评论 (0)编辑 收藏

                                  关于hypertext link的一个tips

在使用html中的hypertext link.元素时发现一个有趣的问题。

我用如下的方式使用一个hypertext link元素。
withouthref.gif
得到效果如下图所示:
text.gif
这个时候该hypertext link对象无法获得焦点。当我把我的代码改成
addhref.gif
就会得到如下效果
url.gif
获得焦点是的效果如下。
foucu.gif
呵呵。这就要我们如果不想用hypertext linkhref时,又想让该对象获得焦点时一定要记得给href属性赋一个空.

posted @ 2006-03-01 19:18 Jet Geng 阅读(532) | 评论 (0)编辑 收藏

开始学习RCP编程

很早很早就听说RCP了。也很想来玩玩,但是一直没有找到好的点子来练手。不过近段时间有个老朋友要求帮他做个小东西。他现在的需求很简单。我怕他以后有要加什么内容。所以就想用RCP来做。刚好用他来好好学习一下,要不都不好意思在bbs.rcp.cn混了。

找了本书(《Eclipse Rich Client Platform Designing Coding and Packaging Java Applications》)按照书中的例子看了起来。

了解基本的:

AbstractUIPlugin

WorkbenchWindowAdvisor

WorkbenchAdvisor

ActionBarAdvisor

IperspectiveFactoryViewPart几个类。

收获最大的就是看到yipsilonbbs.rcp.cn中关于布局的帖子。

http://www.eclipseworld.org/bbs/read.php?tid=1312&page=e#a

public class MGRPerspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {

  Plugin plugin 
= Plugin.getDefault();

  LSEmployee employee 
= plugin.getEmployee();

  
//只有在用户登陆后才能画界面
  if (employee != null) {
    
    String editorArea 
= layout.getEditorArea();
    
    layout.setEditorAreaVisible(
false);
    
    
// 主要界面
    IFolderLayout main = layout.createFolder("main", IPageLayout.TOP, 0.95f, editorArea);
    
// 属性界面
    IFolderLayout property = layout.createFolder("property", IPageLayout.RIGHT, 0.75f"main");
    
// 字典界面
    IFolderLayout dictionary = layout.createFolder("dictionary", IPageLayout.BOTTOM, 0.95f"property");

    LSPosition position 
= employee.getPosition();

    
boolean isManager = position.getManager().booleanValue();

    
if (isManager) {
    main.addView(EmployeeTableView.
class.getName());
    property.addView(PositionPropertyView.
class.getName());
    property.addView(EmployeePropertyView.
class.getName());
    }

    
if (position.getBuyer().booleanValue() || isManager) {
    main.addView(ProviderTableView.
class.getName());
    main.addView(JHInvoiceTableView.
class.getName());
    property.addView(ProviderPropertyView.
class.getName());
    property.addView(JHInvoicePropertyView.
class.getName());
    }

    
if (position.getKeeper().booleanValue() || isManager) {
    dictionary.addView(DDRepositoryView.
class.getName());
    main.addView(DBInvoiceTableView.
class.getName());
    property.addView(DBInvoicePropertyView.
class.getName());
    }

    
if (position.getSeller().booleanValue() || isManager) {
    main.addView(MemberTableView.
class.getName());
    main.addView(YDInvoiceTableView.
class.getName());
    main.addView(XSInvoiceTableView.
class.getName());
    property.addView(MemberPropertyView.
class.getName());
    property.addView(YDInvoicePropertyView.
class.getName());
    property.addView(XSInvoicePropertyView.
class.getName());
    }

    
if (position.getMaintainer().booleanValue() || isManager) {
    dictionary.addView(DDAreaView.
class.getName());
    dictionary.addView(DDBrandView.
class.getName());
    dictionary.addView(DDColorView.
class.getName());
    dictionary.addView(DDCompView.
class.getName());
    dictionary.addView(DDLevelView.
class.getName());
    dictionary.addView(DDSizeView.
class.getName());
    dictionary.addView(DDSortView.
class.getName());
    dictionary.addView(DDDescriptionView.
class.getName());
    }
  }
}
}

根据这段代码做出如下界面:

rcp ui.bmp
很简单。大家见笑了。呵呵。
我的代码就不贴了。看
yipsilon的代码就可以搞定布局了。再次感谢yipsilon。
今天就写到这儿了。争取周末能把ui全部画好。
posted @ 2006-02-23 23:06 Jet Geng 阅读(2385) | 评论 (0)编辑 收藏

定位Eclipse源码

前两天在网上看到一个需要把outline最大化的需求。我就想啊这个Ctrl +M不就的了(呵呵,这个快捷我经常用。快成了条件反射了)。在往下看发现他的需求要求用编程实现。唉这个时候我的Ctrl + M就用不上了。

然后我就想tmd,这个功能既然Eclipse本身已经实现了,那么肯定就回有这样的代码。我需要做的就是把这段代码找出来。好了,确定这个目标就好办了。

下面就得想办法怎么把这个功能地位到Eclipse源码中了。我现在知道得就只是Ctrl + M可以唤醒这部分得功能。其他的就什么都不知道了。那我怎么定位到这部分的源码呢。天哪。我该怎么办啊。

后来理了一理想起来Eclipse中对于快捷键的实现。他们都是通过accelerator来定义的。而accelerator后面一般回对应到一个action。这个action会真真的来完成这个快捷键所要完成的功能。这样一想,心里有了一点底。那么现在就把目标锁定到找到相应的action的实现就算完成了。对于找出相应的action的方法是通过找到Ctrl+M向对应的accelerator

那么这个action会在什么地方实现呢。我就打开了Plug-in Registry视图来随便看看。看看能有什么意外收获。

plug-in.jpg


还真巧在发现了有org.eclipse.ui这个插件。再点进去看到他的Extensions

extends.jpg
居然有Maximize Active view or Editor这个扩展点。大胆猜测org.eclipse.ui会提供一个关于“Maximize Active View or Editor”的实现。为了证实我的猜想,我打开了org.eclipse.uiplugin.xml文件。看到有下面这一段。
command.jpg

这一段证实了我的猜想。

下面如果能找到那各类实现了这个commandok了。找这个就比较容易了。呵呵。只要看看那各类里面有

setActionDefinitionId("org.eclipse.ui.window.maximizePart");

这样的代码就可以搞定了。

最后查得org.eclipse.ui.internal. MaximizePartAction在他的构造函数你发现了这样的代码。
control.jpg
不用多想了,他肯定是实现了这个使视图最大化的功能了。看了他的run函数的内容更加确定就是他了。
run.jpg
而且就是toggleZoom搞定这一切。自己写了测试小测了一下。果然是他。呵呵,这样就完成一次代码定位的过程。爽了一把。离Eclipse宝库又近了一点点。



posted @ 2006-01-22 23:00 Jet Geng 阅读(3111) | 评论 (2)编辑 收藏

仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页