八进制

少年壮志无烟抽

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  244 随笔 :: 0 文章 :: 3241 评论 :: 14 引用

除了普通的类(接口)以外,在类图里可以定义一些特殊的元素,比较常见的是枚举类型、自定义类型,它们对于一个完整可用的模型也是必不可 少的,这篇帖子主要介绍EMF里它们的使用方法。另外,由于EMF对Map的支持比较特别,所以在这里也简要介绍一下Map类型的定义方法。

枚举类型

继续前面帖子的 例子,现在要为产品增加一个评分属性,评分值可以是好中差之一,像这样属性值只能是有限几个值之一的属性就应该定义为枚举类型 (Enumeration)。在类图里首先创建一个名为Score的枚举类型,然后为它增加三个可选值,每个值对应一个唯一的整数值作为标识;然后给 Product类型添加一个名为score的属性,这时的类型列表里已经比原来多了Score类型,我们就选择它作为score属性的类型。重新生成一遍 代码,你会发现增加了Score类(不是接口),运行新生成的编辑器会看到,产品对象的属性里增加了评级,见图1。


图1 枚举类型的属性以下拉列表方式编辑

自定义类型

EMF虽然对大多数java类型做了包装,但是有些情况需要我们使用没有被包含的类型,例如在设计图形化的编辑器(例如类图编辑器)时,图形节点一 般允许选择背景颜色,这就需要一个org.eclipse.swt.graphics.RGB类型的成员变量,而RGB类是SWT提供的类,所以不能通过 创建一个同名类的方式实现,这时就要使用自定义类型。类似的道理,在必须利用遗产项目(Legacy)代码的时候,自定义类型也是必须的。

现在为Product节点增加这样一个名为background的成员变量,步骤如下:首先在类图上新建一个名为RGB的自定义类型(data- type,见图2),将它的Instance Class属性设置为org.eclipse.swt.graphics.RGB;然后给Product类添加一个成员变量background,类型选 择为刚建立的RGB;现在重新生成一遍代码,可以看到Product.java里已经多了这个成员变量,其类型为 org.eclipse.swt.graphics.RGB(因为org.eclipse.swt.graphics.RGB是属于 org.eclipse.swt这个插件的,所以要为com.my.shop项目增加对org.eclipse.swt的依赖才能正确编译)。


图2 新建自定义类型

不过到这里还没有完成全部工作。以为EMF对这个RGB类一无所知,所以它不可能为我们实现RGB对象的持久化,即将RGB类型的数据保存到(缺省 格式的)xml文件中。要解决这个问题得在生成的ShopFactoryImpl里做一些定制,具体来说是修改createRGBFromString ()和convertRGBToString()这两个方法,很明显它们的作用分别是从字符串创建RGB对象以及将RGB对象转换成字符串,我们把它们改 为下面这样。

/**
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated NOT
 
*/
public RGB createRGBFromString(EDataType eDataType, String initialValue) {
    String[] values 
= initialValue.split(",");
    
int red=Integer.parseInt(values[0]);
    
int green=Integer.parseInt(values[1]);
    
int blue=Integer.parseInt(values[2]);
    RGB rgb 
= new RGB(red,green,blue);
    
return rgb;
}

/**
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated NOT
 
*/
public String convertRGBToString(EDataType eDataType, Object instanceValue) {
    RGB rgb 
= (RGB) instanceValue;
    
return rgb.red + "," + rgb.green + "," + rgb.blue;
}

这些代码可以把RGB对象转换为形如“255,90,150”的格式,EMF在持久化时遇到RGB类型的对象就按这样的格式写到文件里。

使用EMap

在类图里可以指定各种类型的成员变量,但使用Map类型则有点特别,直接定义一个EMap类型的成员变量是不可以的,因为EMap并不是继承自 java.util.Map而是EList,也就是说EMF使用EList来模拟实现Map的功能(为什么要这样实现我还没弄清楚)。要实现一个EMap 类型的成员变量,在类图里要参考下面的方式进行定义。

现在我们要为产品类增加一个EMap类型的属性,用这个属性来记录产品每月的销售数量,它维护一个日期字符串(如"2005-09")到当月销售数 量的映射。首先,定义一个名为StringToIntegerMapEntry的新类,这个类将作为Map里的项(Entry);为这个类增加两个属性: 字符串类型的key和整数类型(Integer或int均可)的value;在属性视图里把这个类的Instance Class Name属性设置为java.util.Map$Entry;这样MapEntry类就定义好了,在需要EMap类型变量的类里引用它就可以了,注 意对它的引用必须是包含关系(即“组合”而非“聚合”,类图上连接线用黑色菱形修饰),并且是一对多的。

重新生成一遍代码,在Product接口里salesMap成员变量是这样定义的(因为EMF会检测到我们正在定义一个Map):

/**
 * Returns the value of the '<em><b>Sales Map</b></em>' map.
 * The key is of type {
@link java.lang.String},
 * and the value is of type {
@link java.lang.Integer},
 * <!-- begin-user-doc -->
 * <p>
 * If the meaning of the '<em>Sales Map</em>' containment reference isn't clear,
 * there really should be more of a description here
 * </p>
 * <!-- end-user-doc -->
 * 
@return the value of the '<em>Sales Map</em>' map.
 * 
@see com.my.shop.ShopPackage#getProduct_SalesMap()
 * @model mapType="com.my.shop.StringToIntegerMapEntry" keyType="java.lang.String" valueType="java.lang.Integer"
 * @generated
 
*/
EMap getSalesMap();

这样,在生成的编辑器里可以对每个产品增加新的项,每项包含key和value两个值;在程序里,则应该使用 Product#getSalesMap().put()方法向这个Map里增加数据,因为我们定义的Map项是字符串到整数类型的,所以put()的时 候value参数必须是整数对象(java.lang.Integer),否则会抛出ClassCastException。请记住,不要直接指定 EMap类型,包含MapEntry即可,如果key或value不是普通类型,则使用名为key或value的引用。


图3 编辑器里的EMap类型属性

经过上面几处改动,现在我们的商店模型如下图所示,点此下载项目打包


图4 修改后的模型

posted on 2005-11-28 14:27 八进制 阅读(4340) 评论(9)  编辑 收藏 网摘 所属分类: EclipseEMF

评论

好文

我一直都没有把emf中的这几个类型弄清楚

  回复  引用    

#2楼 2006-03-31 16:20 z.l[未注册用户]
自定义类型 convertRGBToString()方法修改为:
public String convertRGBToString(EDataType eDataType, Object instanceValue) {
if(instanceValue==null){
return super.convertToString(eDataType, instanceValue);
}
RGB rgb = (RGB) instanceValue;
return rgb.red + "," + rgb.green + "," + rgb.blue;
}

  回复  引用    

#3楼 2007-06-11 20:52 zoey[未注册用户]
怎么我在选择 instance class 的时候没有org.eclipse.swt.graphics.RGB可选择啊?填入org.eclipse.swt.graphics.RGB的时候不能点finish。
我还是新手,请多指教~~
还有,在rose里面怎么添加或建立datatype类啊?

  回复  引用    

#4楼[楼主] 2007-06-12 22:12 八进制      
是在哪里不能finish?
  回复  引用  查看    

#5楼 2007-06-13 21:41 zoey[未注册用户]
首先在类图上新建一个名为RGB的自定义类型(data- type,见图2),将它的Instance Class属性设置为org.eclipse.swt.graphics.RGB;

Instance Class的属性选择里没有org.eclipse.swt.graphics.RGB;

自己键入的话就不能点finish了。自己键入是不行的吧?

  回复  引用    

#6楼[楼主] 2007-06-14 10:06 八进制      
有可能,让你的项目依赖swt,或者在classpath里增加swt对应的jar包试试。
  回复  引用  查看    

#7楼 2007-06-14 10:40 jie[未注册用户]
八兄,您好!感谢你给我们这些初学者贡献这么好的入门资料!就是以前我用GEF做了个简单的图形编辑器。我现在就是想学着用EMF构件模型,GEF引用EMF中的模型进行修改原先那个简单的流程编辑器。就是现在我有个非常愚笨的问题想请教你:
不是在EMF中它能将模型文件保存为XML格式文件,那在现在我的EMF+GEF工程中如何保存图形编辑器中的各个图形信息啊?实在我的Editor中保存么?
恳请八兄指点指点小弟一下!!万分感激!!

  回复  引用    

#8楼[楼主] 2007-06-14 13:42 八进制      
EMF+GEF的情况下,图形信息一般作为业务信息的一部分,例如业务模型里有Book这个类,它有name和price属性,为了使用GEF,你还要给它加上x和y属性。

save工作还是在editor里做,比如在doSave()方法里。你可以参考这篇:http://www.cnblogs.com/bjzhanghao/archive/2005/04/15/138447.html" target="_new">http://www.cnblogs.com/bjzhanghao/archive/2005/04/15/138447.html,把例子下载下来看看就知道了。

  回复  引用  查看    

属性图示中找不到Instance Class Name属性
  回复  引用    

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 286078


相关文章:

相关链接: