<!--[if !supportLists]-->1. <!--[endif]-->模型:
<!--[if !supportLists]-->a) <!--[endif]-->说明:这是用于我们下文进行讨论的模型。
<!--[if !supportLists]-->b) <!--[endif]-->UML图:
<!--[endif]-->
<!--[if !supportLists]-->c) <!--[endif]-->Ecore图:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]-->2. <!--[endif]-->EMF.Ecore-Package & Factory
<!--[if !supportLists]-->a) <!--[endif]-->包遍历:
<!--[if !supportLists]--> i. <!--[endif]-->说明:通过EPackage我们可以访问一个包里面的所有模型信息。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
public void introspect() {
EPackage p = PoPackage.eINSTANCE;
Iterator ci = p.getEClassifiers().iterator();
for (; ci.hasNext();) {
EClassifier cla = (EClassifier) ci.next();
if (cla instanceof EClass) {
EClass eClass = (EClass) cla;
System.out.println(eClass.getName() + "{");
Iterator ai = eClass.getEAttributes().iterator();
for (; ai.hasNext();) {
EAttribute eattr = (EAttribute) ai.next(); System.out.println("/t Attr:" + eattr.getName());
}
Iterator ri = eClass.getEReferences().iterator(); for (; ri.hasNext();) {
EReference eref = (EReference) ri.next();
System.out.println("/t Ref:" + eref.getName());
}
System.out.println("}");
} else if (cla instanceof EEnum) {
EEnum eEnum = (EEnum) cla;
Iterator ei = eEnum.getELiterals().iterator();
for (; ei.hasNext();) {
EEnumLiteral liter = (EEnumLiteral) ei.next();
System.out.println("EnumLiterl:" + liter.getName());
}
} else if (cla instanceof EDataType) {
EDataType eDataType = (EDataType) cla;
System.out.println("DataType:" + eDataType.getName());
}
}
}
<!--[if !supportLists]--> iii. <!--[endif]-->输出:
PurchaseOrder{
Attr:comment
Attr:orderDate
Attr:status
Attr:totalAmount
Ref:items
Ref:shipTo
Ref:previousOrder
Ref:customer
Ref:previouseOrder
}
Item{…}
…
EnumLiterl:Pending
…
DataType:Date
DataType:SKU
<!--[if !supportLists]-->b) <!--[endif]-->对象创建
<!--[if !supportLists]--> i. <!--[endif]-->说明:通过EPackage和EFactory我们可以创建包中对象的实例。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
public Object createObject(String className,String nsURI){
EPackage p = EPackage.Registry.INSTANCE.getEPackage(nsURI);
EClass eClass = (EClass) p.getEClassifier(className);
EFactory factory = p.getEFactoryInstance();
EObject obj = factory.create(eClass);
return obj;
}
注:我们通过包的nsURI值来获取对应的EPackage引用,然后再根据所需要实例化的类名,
在包之中找到对应的EClassifer,最后实例化的工作将由EFactory来完成。由于我们通
过EPackage.Registry.INSTANCE来获取已注册的EPackage实例,所以该程序只能在插件
运行后才能使用,因为nsURI的关联是在插件初始化的过程中完成的。而如果我们直接使
用PoPackage.eINSTACNCE的话,那么上述问题将不存在。
<!--[if !supportLists]-->3. <!--[endif]-->EMF.Ecore-元模型操作
<!--[if !supportLists]-->a) <!--[endif]-->对象查询:
<!--[if !supportLists]--> i. <!--[endif]-->代码:
public static void main(String[] args) {
Item item = PoFactory.eINSTANCE.createItem();
item.setProductName("Apple");
item.setUSPrice(50);
item.setQuantity(4);
printAttributes(item);
}
public static void printAttributes(EObject eobj) {
EClass ec = eobj.eClass();
Iterator ai = ec.getEAllAttributes().iterator();
EAttribute attr = null;
Object value = null;
for (; ai.hasNext();) {
attr = (EAttribute) ai.next();
value = eobj.eGet(attr);
if (eobj.eIsSet(attr))
System.out.println(attr.getName() + " : " + value);
}
}
<!--[if !supportLists]--> ii. <!--[endif]-->输出:
productName : Apple
quantity : 4
USPrice : 50
<!--[if !supportLists]-->b) <!--[endif]-->PoSwitch类
<!--[if !supportLists]--> i. <!--[endif]-->代码:
public static void main(String[] args) {
Supplier sup = PoFactory.eINSTANCE.createSupplier();
sup.setName("Sup1");
Customer cus = PoFactory.eINSTANCE.createCustomer();
cus.setCustomerID(1);
PurchaseOrder po = PoFactory.eINSTANCE.createPurchaseOrder();
po.setComment("po1");
Item item = PoFactory.eINSTANCE.createItem();
item.setProductName("Item1");
po.getItems().add(item);
sup.getOrders().add(po);
sup.getCustomers().add(cus);
PoSwitch switcher = new PoSwitch() {
public Object caseItem(Item obj) {
System.out.println("Item:" + obj.getProductName());
return obj;
}
public Object casePurchaseOrder(PurchaseOrder obj) {
System.out.println("PurchaseOrder:" + obj.getComment());
return obj;
}
public Object caseCustomer(Customer obj) {
System.out.println("Customer:" + obj.getCustomerID());
return obj;
}
public Object caseSupplier(Supplier obj) {
System.out.println("Supplier:" + obj.getName());
return obj;
}
};
Iterator it = EcoreUtil.getAllContents(Collections.singleton(sup));
for (; it.hasNext();) {
EObject obj = (EObject) it.next();
switcher.doSwitch(obj);
}
}
<!--[if !supportLists]--> ii. <!--[endif]-->输出:
Supplier:Sup1
Customer:1
PurchaseOrder:po1
Item:Item1
<!--[if !supportLists]--> iii. <!--[endif]-->说明:PoSwitch类是由EMF所生成的用于查询某一个类的类型的。在PoAdapterFactory内部,他也是先通过该PoSwitch类,查询到对应的类型,然后才调用带类型的createXyzAdapter()方法。
<!--[if !supportLists]-->c) <!--[endif]-->跨文档引用
<!--[if !supportLists]--> i. <!--[endif]-->说明:在EMF当中,由于可能存在一个资源引用另外一个资源中的内容,所以EMF提供了一种用于跨文档进行查询的方法。这需要通过ResourceSet来实现,由于不同的资源在EMF当中是使用Resource来表示,而所有的Resource都由ResourceSet来管理,因此通过ResourceSet我们就能够查询到其他资源中的内容。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
常规的做法:查询在其他文档当中引用了po的类。
PurchaseOrder po = …;
Col lection refs = EcoreUtil.UsageCrossReferencer.find(po,
po.eResource().getResourceSet());
定制:
PurchaseOrder po = …;
Col lection refs = new EcoreUtil.UsageCrossReferencer(
po.eResource().getResourceSet()){
protected boolean crossReference(EObject object,
EReference eReference,
EObject crossReferencedObject){
return …;
}
public Col lection findUsage(EObject object){
return super.findUsage(object);
}
public Boolean containment(EObject eObject){
return …;
}
}.findUsage(order);
说明:当我们对UsageCrossReferencer进行子类化时,我们可以重载其中的一些方法来对搜索进行优化,其中crossReference()用于控制把什么对象添加到结果集;containment()用于判断是否需要对当前对象的子对象进行查询;而findUsage()就是返回结果集,由于该方法原来是protected的,所以我们需要通过重载把他改成public以便调用。UsageCrossReferencer的搜索策略是,对传入他构造函数的集合进行遍历(这里就是po.eResource().getResourceSet()),他先访问当前对象,然后根据containment()来判断是否需要继续对子类进行递归访问。当访问当前对象时(obj),他调用obj的eCrossReferences()方法。然后再调用crossReference()方法,如果该方法返回true,则该obj将被添加入最后的结果集当中。
obj = …;
EReference eReference = obj.eCrossReferences();
EObject owner = eReference. eContainer();
if(crossReference(owner,eReference,obj)){
result.add(obj);
}
<!--[if !supportLists]-->d) <!--[endif]-->动态EMF
<!--[if !supportLists]--> i. <!--[endif]-->说明:我们可以通过UML,Java,XML来生成Ecore模型,然后生成Ecore代码。然后再在这些代码之上进行操作,这称为静态EMF。我们也可以使用动态EMF,即不通过上述的步骤,而直接产生符合模型要求的代码。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:生成一个Item实例。
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EcorePackage ecorePackage = EcorePackage.eINSTANCE;
EClass itemClass = ecoreFactory.createEClass();
itemClass.setName("Item");
EAttribute comment = ecoreFactory.createAttribute();
comment.setName("Comment");
comment.setEType(ecorePackage.getEString());
itemClass.getEAttributes().add(comment);
EPackage package = ecoreFactory.createEPackage();
package.setName("po");
package.getEClassifiers().add(itemClass);
EFactory factory = package.getEFactoryInstance();
EObject item = factory.create(itemClass);
item.eSet(comment, "Item1");
说明:上面红色的部分,就是创建了一个叫做po的包,然后包里面有一个叫做Item的类,
Item类有一个Comment的属性。然后蓝色的部分就是生成了一个Item实例,并设置他的
Comment属性的值为Item1。所谓的动态EMF主要指的是红色的部分,即不通过UML,Java,
XML等 方法 先生成用于描述模型的EMF代码,而是直接使用EcoreFactory在内存中生成模
型的结构。蓝色部分的使用跟静态方式是基本一致的。这里我们使用EcoreFactory来创建
某一类对象,用EcorePackage来获取某一种类型,这与生成模型实例时我们使用EFacotry
和EPackage是类似的,只是EFactory是用于生成模型实例,而EcoreFacotry用于生成模
型。
<!--[if !supportLists]-->4. <!--[endif]-->EMF.edit-ResourceSet & Resource
<!--[if !supportLists]-->a) <!--[endif]--> UR I & URIConverter
<!--[if !supportLists]--> i. <!--[endif]-->说明:在EMF当中,不管是资源本身,还是资源所包含的节点树当中的节点,都是通过URI来管理的。而EMF通过URIConverter类来实现URI和具体文件或资源的关联。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
public void normalize() {
URIConverter con = new URIConverterImpl();
URI uri1 = URI.createURI("http:///somemodel.ecore/");
URI uri2 = URI.createURI("platform:/resource/project/somemodel.ecore/");
con.getURIMap().put(uri1, uri2);
URI normalized = con.normalize(uri1);
System.out.println("before:" + uri1);
System.out.println("after:" + normalized);
normalized = con.normalize(URI
.createURI("http:///somemodel.ecore/#hello"));
System.out.println("before:"
+ URI.createURI("http:///somemodel.ecore/#hello"));
System.out.println("after:" + normalized);
}
<!--[if !supportLists]--> iii. <!--[endif]-->输出:
before:http:///somemodel.ecore/
after:platform:/resource/project/somemodel.ecore/
before:http:///somemodel.ecore/#hello
after:platform:/resource/project/somemodel.ecore/#hello
<!--[if !supportLists]-->b) <!--[endif]-->资源管理:
<!--[if !supportLists]--> i. <!--[endif]-->说明:Resource是用于存放模型数据的抽象。ResourceSet用于对Resource进行管理。当我们需要新建一个Resource时,我们调用ResourceSet上的createResource()方法,这个方法会把请求转发到ResourceFactory,而由ResourceFactory最终完成Resource的创建。
<!--[if !supportLists]--> ii. <!--[endif]-->模型:
create |
manager |
ResourceFactory |
ResourceSet |
Resource |
Resource |
Resource |
<!--[if !supportLists]--> iii. <!--[endif]-->资源创建:
<!--[if !supportLists]-->1. <!--[endif]-->代码:
public void write(String filename) throws IOException {
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().
put("*",new XMLResourceFactoryImpl());
ResourceSet resourceSet = new ResourceSetImpl();
URI fileURI = URI.createURI("supplier.po");
Resource resource = resourceSet.createResource(fileURI);
Supplier sup = PoFactory.eINSTANCE.createSupplier();
sup.setName("S1");
Customer cus1 = PoFactory.eINSTANCE.createCustomer();
cus1.setCustomerID(1);
Customer cus2 = PoFactory.eINSTANCE.createCustomer();
cus2.setCustomerID(2);
sup.getCustomers().add(cus1);
sup.getCustomers().add(cus2);
PurchaseOrder po1 = PoFactory.eINSTANCE.createPurchaseOrder();
po1.setComment("PO1");
PurchaseOrder po2 = PoFactory.eINSTANCE.createPurchaseOrder();
po1.setComment("PO2");
sup.getOrders().add(po1);
sup.getOrders().add(po2);
cus1.getOrders().add(po1);
cus1.getOrders().add(po2);
resource.getContents().add(sup);
resource.save(null);
}
<!--[if !supportLists]-->2. <!--[endif]-->结果:
<?xml version="1.0" encoding="ASCII"?>
<po:Supplier xmlns:po="http:///po.ecore" name="S1">
<customers customerID="1" orders="//@orders.0 //@orders.1"/>
<customers customerID="2"/>
<orders comment="PO2" customer="//@customers.0"/>
<orders customer="//@customers.0"/>
</po:Supplier>
<!--[if !supportLists]-->3. <!--[endif]-->说明:这里演示了如何添加单值,多值属性,包含和非包含引用。蓝色表示包含引用,包含引用会在目标文件中作为子节点添加。红色表示非包含引用,非包含引用会在目标文件中作为属性添加。
<!--[if !supportLists]--> iv. <!--[endif]-->资源读取:
<!--[if !supportLists]-->1. <!--[endif]-->代码:
public EObject read(String fragment,String file){
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().
put("*",new XMLResourceFactoryImpl());
ResourceSet rs = new ResourceSetImpl();
Resource r = rs.getResource(URI.createURI(file), true);
try {
r.load(null);
EObject obj = r.getEObject(fragment);
} catch (IOException e) {
e.printStackTrace();
}
}
<!--[if !supportLists]-->2. <!--[endif]-->说明:该程序必须在插件运行后才能正确运行,因为资源的关联是在插件初始化的过程中完成的。fragment是一个类似于XPath语法的路径表达式,像"//@customers.0"等。
<!--[if !supportLists]-->c) <!--[endif]-->资源管理实现
<!--[if !supportLists]--> i. <!--[endif]-->说明:EMF使用了XML和XMI的方式来存储资源,在存储和读取的过程中,我们可以同过传入一个HashMap来对存储和读取的过程进行定制。
<!--[if !supportLists]-->5. <!--[endif]-->EMF.edit-Adapter
<!--[if !supportLists]-->a) <!--[endif]-->说明:我们可以使用三种方式给对象添加额外的监听器。
<!--[if !supportLists]-->b) <!--[endif]-->直接式:
<!--[if !supportLists]--> i. <!--[endif]-->代码:
public class Some Ada pter extends Ada pterImpl{
public void notifyChanged(Notification notification) {
…
}
}
public static void main(String[] args){
USAddress address = PoFactory.eINSTANCE.createUSAddress();
address.eAdapters().add(new SomeAdapter());
…
}
<!--[if !supportLists]--> ii. <!--[endif]-->说明:这种方式需要获取模型对象的eAdapters列表,直接进行添加。
<!--[if !supportLists]-->c) <!--[endif]-->扩展AdapterFactoryImpl:
<!--[if !supportLists]--> i. <!--[endif]-->代码:
public class Some Ada pter extends Ada pterImpl{
public void notifyChanged(Notification notification) {
…
}
public boolean isAdapterForType(Object type){
return type == SomeAdapter.class;
}
}
public class SomeAdapterFactory extends AdapterFactoryImpl{
public boolean isFactoryForType(Object type){
return type == SomeAdapter.class;
}
public Ada pter createAdapter(Notifier target){
return new SomeAdapter();
}
}
public static void main(String[] args){
USAddress address = PoFactory.eINSTANCE.createUSAddress();
new SomeAdapterFactory.adapt(address,SomeAdapter.class);
…
}
<!--[if !supportLists]--> ii. <!--[endif]-->说明:这种方式并不直接对对象的监听器列表进行操作,而是通过AdapterFactory的adapt()方法。在该方法内部,他会先遍历模型对象的eAdapters列表,看是否有支持对应类型的适配器存在,如果没有的话,他会调用createAdapter()方法,来创建一个新的适配器,并添加到eAdapters列表当中。
<!--[if !supportLists]-->d) <!--[endif]-->扩展模型的PoAdapterFactory:
<!--[if !supportLists]--> i. <!--[endif]-->代码:
public class SomeAdapterFactory extends PoAdapterFactory {
public Adapter createAddressAdapter() {
return new SomeAdapter();
}
}
public static void main(String[] args){
USAddress address = PoFactory.eINSTANCE.createUSAddress();
new SomeAdapterFactory.adapt(address,SomeAdapter.class);
…
}
<!--[if !supportLists]--> ii. <!--[endif]-->说明:这种方式与第二种类似,不同的地方是,他没有实现createAdapter()方法,而是实现了创建某一特定类型的createXyzAdapter()。这是因为在PoAdapterFactory内部,他的createAdapter()方法,会根据所传入的对象行进一个switch,然后根据匹配的结果调用创建对应类型的createXyzAdapter()方法。另外,这里要注意的是,虽然我们实现的不是createUSAddressAdapter(),而是createAddressAdapter()方法,但照样成功的执行。这是因为在PoAdapterFactory中,createUSAddressAdapter()方法返回空,这会导致PoAdaperFactory根据继承链调用USAddress的父类Address的createAddressAdapter()方法。
<!--[if !supportLists]-->e) <!--[endif]-->注册AdapterFactory
<!--[if !supportLists]--> i. <!--[endif]-->说明:以上这几种方式都是需要我们显式的去进行适配,在一般情况下,我们更通常的做法是向模型所在的ResourceSet进行注册。从而可以在需要的时候,让系统自己添加合适的Adapter。由于需要依赖已经存在的ResultSet实例,因此需要在插件启动之后才能进行。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
ResourceSet rs = …
rs.getAdapterFactories().add(new SomeAdapterFactory());
// 然后在需要的时候
EcoreUtil.getRegisteredAdapter(address,SomeAdapter.class);
在getRegisteredAdapter()内部他会通过模型实例,查找他所在的ResourceSet然后通过该ResourceSet获取支持对应类型的AdapterFactory,然后调用该Factory的adapt()方法。
<!--[if !supportLists]-->f) <!--[endif]-->优化通知事件处理:
<!--[if !supportLists]--> i. <!--[endif]-->说明:当发生了属性修改事件时,而且该属性的类型是基本类型时,我们可以采用以下两个方式来对通知内容的获取进行优化。
<!--[if !supportLists]--> ii. <!--[endif]-->代码:
假定我们对USAddress进行监听。
public void notifyChanged(Notification notification){
switch(notification.getFeatureID(USAddress.class)){
case PoPackage.USAddress__CITY:
int oldValue = notification.getOldIntValue();
int newValue = notification.getNewIntValue();
brea k;
case Po Package.USAddress__COUNTRY:…
brea k;
}
}
说明:我们也可以通过先调用notification.getFeature()方法,然后再用if-else的方法来判断是哪个属性进行修改。但上述方式的优点就是要轻量的多。另外一点就是,当我们获取属性修改值时,我们调用了有类型的getOldIntValue()方法,这样做的原因是,当属性是基本类型时,那么在拼装Notification实例的时候,EMF将只会往里面填入基本类型,因此,如果我们在获取的时候直接调用不带类型的getOldValue(),那么他将需要把基本类型先通过对应的Wrapper类把他封装起来,这将导致性能上的损耗。
<!--[if !supportLists]-->6. <!--[endif]-->EMF.edit-Commands重载
<!--[if !supportLists]-->a) <!--[endif]-->说明:由于在EMF中,对模型的修改是通过Command来完成的, 因此,我们需要一种对Command进行定制的方法。由于在EMF.edit当中,当需要进行模型操作时,他都会通过对应的XyzItemProvider的createXxxCommand()来完成,而一般情况下XyzItemProvider会调用他的父类ItemProviderAdapter对应的createXxxCommand(),所以,当我们需要改变这种默认的行为时,我们只需要在对应的XyzItemProvider内部重载这个createXxxCommand()即可。
<!--[if !supportLists]-->b) <!--[endif]-->代码:
public class XyzItemProvider exnteds ItemProviderAdapter{
public Command createXxxCommand(EditingDomain domain,EObject owner,
EStructuralFeature feature,Object value){
return new MyXxxCommand(domain,owner,feature,value){};
}
public Command createYyyCommand(EditingDomain domain,EObject owner,
EStructuralFeature feature,Object value){
return new MyYyyCommand(domain,owner,feature,value){};
}
}
public class MyXxxCommand extends XxxCommand{
public MyCommand(EditingDomain domain,EObject owner,EStructuralFeature feature,
Object value){
super(domain,owner,feature,value);
}
public void doExcute(){
…;
super.doExcute();
}
}
public class MyYyyCommand extends CompoundCommand{
protected EditingDomain domain;
protected …;
public MyYyyCommand(EditingDomain domain,EObject owner,
EStructuralFeature feature,Object value){
this.domain = domain;
…
append(new ZzzCommand(domain,owner,feature,value));
}
public void excute(){
super.excute();
…;
appendAndExcute(new AaaCommand());
}
}
说明:在MyXxxCommand当中我们扩展了某一已有的XxxCommand,所以我们可以通过调用super()方法,来对属性进行保存,而这种情况下,我们重载的是doExcute()方法。在MyYyyCommand当中,由于我们扩展的是CompoundComand,所以我们需要自己来保存这些变量。CompoundCommand是指,在这个命令内部可以组合多个命令,这通过append()来完成。在MyYyyCommand类当中,我们重载的是excute()方法,并且调用了super.excute()来执行已经append在队列当中的命令,之后当如果我们需要增加命令时,我们可以使用appendAndExcute()方法。
<!--[if !supportLists]-->7. <!--[endif]-->EMF.editor-编辑器定制:
<!--[if !supportLists]-->a) <!--[endif]-->根节点显示:修改Editor的createPages()方法。
<!--[if !supportLists]--> i. <!--[endif]-->图前:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> ii. <!--[endif]-->代码前:
public void createPages() {
…
selectionViewer.setInput(editingDomain.getResourceSet()); viewerPane.setTitle(editingDomain.getResourceSet());
…
}
<!--[if !supportLists]--> iii. <!--[endif]-->图后:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> iv. <!--[endif]-->代码后:
public void createPages() {
…
ResourceSet rs = (Resource)editingDomain.getResourceSet();
Resource res = rs.getResources().get(0);
selectionViewer.setInput(res);
viewerPane.setTitle(res);
…
}
<!--[if !supportLists]-->b) <!--[endif]-->子节点显示:修改对应的XxxItemProvider的getChildrenFeatures()方法。
<!--[if !supportLists]--> i. <!--[endif]-->图前:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> ii. <!--[endif]-->代码前:
public Collection getChildrenFeatures(Object object) {
if (childrenFeatures == null) {
super.getChildrenFeatures(object); childrenFeatures.add(PoPackage.eINSTANCE.getPurchaseOrder_Items()); childrenFeatures.add(PoPackage.eINSTANCE.getPurchaseOrder_ShipTo());
}
return childrenFeatures;
}
<!--[if !supportLists]--> iii. <!--[endif]-->图后:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> iv. <!--[endif]-->代码后:
public Collection getChildrenFeatures(Object object) {
if (childrenFeatures == null) {
super.getChildrenFeatures(object); childrenFeatures.add(PoPackage.eINSTANCE.getPurchaseOrder_Items()); //childrenFeatures.add(PoPackage.eINSTANCE.getPurchaseOrder_ShipTo());
}
return childrenFeatures;
}
<!--[if !supportLists]-->c) <!--[endif]-->属性编辑:修改对应的XyzItemProvider的getPropertyDescriptors()方法。
<!--[if !supportLists]--> i. <!--[endif]-->图前:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> ii. <!--[endif]-->代码前:
public List getPropertyDescriptors(Object object) {
if (itemPropertyDescriptors == null) {
super.getPropertyDescriptors(object);
addCommentPropertyDescriptor(object);
addOrderDatePropertyDescriptor(object);
addStatusPropertyDescriptor(object);
addTotalAmountPropertyDescriptor(object);
addCustomerPropertyDescriptor(object);
}
return itemPropertyDescriptors;
}
<!--[if !supportLists]--> iii. <!--[endif]-->图后:
<!--[if !vml]--><!--[endif]-->
<!--[if !supportLists]--> iv. <!--[endif]-->代码后:
public List getPropertyDescriptors(Object object) {
if (itemPropertyDescriptors == null) {
super.getPropertyDescriptors(object);
…
addAddressPropertyDescriptor(((PurchaseOrder) object).getShipTo(),
getString("_UI_PurchaseOrder_shipTo_feature"));
}
return itemPropertyDescriptors;
}
private void addAddressPropertyDescriptor(Address address,final String feature){
AddressItemProvider pro = (AddressItemProvider) adapterFactory.adapt(
address, IItemPropertySource.class);
List aDes = pro.getPropertyDescriptors(address);
for (Iterator iter = aDes.iterator(); iter.hasNext();) {
ItemPropertyDescriptor des = (ItemPropertyDescriptor) iter.next();
itemPropertyDescriptors.add(new ItemPropertyDescriptorDecorator(
address, des) {
public String getCategory(Object obj) {
return feature;
}
public String getId(Object obj) {
return feature + getDisplayName(obj);
}
});
}
}
<!--[if !supportLists]-->d) <!--[endif]-->定制Editor中的Viewer
<!--[if !supportLists]--> i. <!--[endif]-->说明:
<!--[if !supportLists]-->1. <!--[endif]-->EMF.editor当中定义了很多Viewer,这些Viewer的初始化是在createPages()方法中实现的,所以,如果我们想定制这些Viewer的类型和行为,我们修改该方法。
<!--[if !supportLists]-->2. <!--[endif]-->当在Outline中点选某个节点后将触发handleContentOutlineSelection()方法,我们可以在这里面对Viewer的动态行为进行定制。
<!--[if !supportLists]-->3. <!--[endif]-->EMF.editor当中定义的TableViewer所使用的LableProvider是由XyzItemAdapter实现的,但XyzItemAdapter本身只实现了IItemLabelProvider,而没有实现ITableItemLabelProvider,所以他不能提供根据列而返回不同的text,为此我们可以让XyzItemProvider实现ITableItemLabelProvider,同时我们需要在EMF.edit的PoItemProviderAdapterFactory的构造函数中添加一行。
public PoItemProviderAdapterFactory() {
supportedTypes.add(IStructuredItemContentProvider.class);
supportedTypes.add(ITreeItemContentProvider.class);
supportedTypes.add(IItemPropertySource.class);
supportedTypes.add(IEditingDomainItemProvider.class);
supportedTypes.add(IItemLabelProvider.class);
supportedTypes.add(ITableItemLabelProvider.class);
}