EMF进阶功能

<!--[if !supportLists]-->1.   <!--[endif]-->模型:

<!--[if !supportLists]-->a)        <!--[endif]-->说明:这是用于我们下文进行讨论的模型。

<!--[if !supportLists]-->b)        <!--[endif]-->UML图:

<!--[if !vml]--><!--[endif]-->

 

 

 

 

 

 

<!--[if !supportLists]-->c)        <!--[endif]-->Ecore图:

<!--[if !vml]--><!--[endif]-->

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<!--[if !supportLists]-->2.   <!--[endif]-->EMF.EcorePackage & 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]-->说明:通过EPackageEFactory我们可以创建包中对象的实例。

 

<!--[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),他调用objeCrossReferences()方法。然后再调用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]-->说明:我们可以通过UMLJavaXML来生成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主要指的是红色的部分,即不通过UMLJava

XML等 方法 先生成用于描述模型的EMF代码,而是直接使用EcoreFactory在内存中生成模

型的结构。蓝色部分的使用跟静态方式是基本一致的。这里我们使用EcoreFactory来创建

某一类对象,用EcorePackage来获取某一种类型,这与生成模型实例时我们使用EFacotry

EPackage是类似的,只是EFactory是用于生成模型实例,而EcoreFacotry用于生成模

型。

 

<!--[if !supportLists]-->4.   <!--[endif]-->EMF.editResourceSet & 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 !vml]--> <!--[endif]-->

 

<!--[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使用了XMLXMI的方式来存储资源,在存储和读取的过程中,我们可以同过传入一个HashMap来对存储和读取的过程进行定制。

 

<!--[if !supportLists]-->5.   <!--[endif]-->EMF.editAdapter

<!--[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]-->说明:这种方式并不直接对对象的监听器列表进行操作,而是通过AdapterFactoryadapt()方法。在该方法内部,他会先遍历模型对象的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的父类AddresscreateAddressAdapter()方法。

 

<!--[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,然后调用该Factoryadapt()方法。

 

<!--[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.editCommands重载

<!--[if !supportLists]-->a)        <!--[endif]-->说明:由于在EMF中,对模型的修改是通过Command来完成的, 因此,我们需要一种对Command进行定制的方法。由于在EMF.edit当中,当需要进行模型操作时,他都会通过对应的XyzItemProvidercreateXxxCommand()来完成,而一般情况下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]-->根节点显示:修改EditorcreatePages()方法。

<!--[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]-->子节点显示:修改对应的XxxItemProvidergetChildrenFeatures()方法。

<!--[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]-->属性编辑:修改对应的XyzItemProvidergetPropertyDescriptors()方法。

<!--[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.editPoItemProviderAdapterFactory的构造函数中添加一行。

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);

          }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值