1. Model:
a) Description: This is the model for us to discuss below.
b) UML map:
c) ecore diagram:
2. EMF.ecore-Package & Factory
a) package traversal:
i. Description: We can access all model information in a package via epackage.
ii. code:
Public void introspect () {
Epackage P = POPACKAGE.EINSTANCE;
Iteclass ci = p.geteclassifiers (). Itrator ();
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.Getereference (). 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 (clal instanceof edtatype) {
EDATYPE EDATATYPE = (EDATATYPE) CLA;
System.out.println ("DataType:" EDATYPE.GETNAME ());
}
}
}
iii. Output:
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
b) created
i. Description: We can create an instance of the object in the package via Epackage and Efactory.
ii. code:
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;
}
Note: We obtain the corresponding EPAckage reference through the package of NSURI values, and then according to the names required by the required instantiation.
Find the corresponding ECLASSIFER in the package, the final instantiated work will be completed by eFactory. Because of us
After epackage.registry.instance, get the registered Epackage instance, so the program can only be in the plugin.
You can use it after running because the association of NSURI is done during the initialization of the plugin. And if we directly
With POPAGKAGE.EINSTACNCE, then the above problems will not exist.
3. EMF.ecore-meta model operation
a) object query:
i. code:
Public static void main (string [] args) {item item = POFActory.einstance.createItem ();
Item.SetProductName ("apple");
Item.setusprice (50);
Item.Setquantity (4);
PrintaTRibutes (item);
}
Public Static Void PrintAttributes (eObject eobj) {
ECLASS EC = eobj.eclass ();
Iterator ai = ec.geteallattributes (). Itrator ();
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);
}
}
ii. Output:
ProductName: Apple
Quantity: 4
USPRICE: 50
b) Poswitch class
i. code:
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.getRDERS (). 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 CaseCustom (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 (Collectes.singleton (SUP));
For (; it.hasnext ();) {
EOBJECT OBJ = (EOBJECT) IT.NEXT ();
Switcher.doswitch (obj);
}
}
ii. Output:
Supplier: SUP1
Customer: 1
PurchaseOrder: Po1
Item: item 1
iii. Description: The Poswitch class is the type of type used by the EMF to query a certain class. Inside the POADAPTERFAACTORY, he also first queries the corresponding type through this Poswitch class, then call the type of Createxyzadapter () method.
c) cross-document reference
i. Description: In EMF, since there may be a resource reference to the content in another resource, EMF provides a use The method of querying in cross documents. This needs to be implemented via ResourceSet, because different resources are represented in EMF, and all Resource is managed by ResourceSet, so we can query content in other resources via ResourceSet.
ii. code:
General practices: Query references the PO class in other documents.
PurchaseORDER PO = ...
COL
Lection refs = ecoreutil.usagecrossReferencer.find (PO,
PO.Resource (). getresourceset ());
custom made:
PurchaseORDER PO = ...
COL
Lection refs = new ecoreutil.usagecrossReferencer (
PO.Resource (). 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);
Description: When we subcatenate for usagecrossReferencer, we can overload some of these methods to optimize search, where crossReference () is used to add what object to the result set; Containment () is used to determine if it is needed The current object's child object is queried; and FINDUSAGE () is the return result set. Since the method is protected by protected, we need to change him into public for call. UsageCrossReference's search strategy is to traverse the collection of the incoming constructor (here is Po.Resource (). GetResourceSet ()), he first access the current object, then determine if the subclass is required according to Containment () Recursive access. When the current object is accessed (OBJ), he calls the OBJ's EcrossReference () method. Then then call the crossReference () method, if the method returns true, the OBJ will be added to the last result set.
Obj = ...
EREFERENCE EREference = obj.ecroSReference ();
EOBJECT OWNER = EREMERENCE. ECONTAINER ();
IF (CrossReference (Owner, EREference, Obj)) {
Result.Add (OBJ);
}
D) -> Dynamic EMF
i. Description: We can generate the Ecore model via UML, Java, XML, then generate ECORE code. Then operate on these code, which is called static EMF. We can also use dynamic EMF, ie, without passing the above steps, and directly generates code that meets the model requirements.
ii. Code: Generate an Item instance.
Ecorefactory ecorefactory = ecorefactory.einstance;
Ecorepackage ecorepage = ecorepackage.einstance;
Eclass itemclass = ecorefactory.createeclass ();
Itemclass.setname ("item");
Eattribute comment = ecorefactory.createAttribute ();
Comment.setname ("comment");
Comment.seType (ecorepackage.geteString ());
Itemclass.getettributes (). add (comment);
Epackage package = ecorefactory.createepage ();
Package.setname ("Po");
Package.geteclassifiers (). Add (itemclass);
Efactory factory = package.getefactoryInstance (); eobject item = factory.create (itemclass);
Item.eet (Comment, "Item1");
Description: The above red part is to create a package called Po, then there is a class named Item,
The Item class has a Comment property. Then the blue part is generated an Item instance and set his
The value of the Comment property is Item1. The so-called dynamic EMF mainly refers to the red part, that is, not through UML, Java,
XML, etc.
method
Mr. is used to describe the EMF code of the model, but directly use eCoreFactory to generate an mode in memory.
Type structure. The use of the blue part is basically consistent with the static method. Here we use eCoreFactory to create
A type of object, with ecorepackage to get some type, which is used as EFAotry when instance of generating model
And ePackage is similar, just eFactory is used to generate model instances, while ecorefacotry is used to generate molds.
type.
4. EMF.EDIT-RESOURCESET & RESOURCE
a)
UR
I & Uriconverter
i. Description: In EMF, whether it is the resource itself, or the node in the node tree contained in the resource, is through the URI Manage. EMF implements the URI and specific files or resources associations through the Uriconverter class.
ii. code:
Public void normalize () {
Uriconverter con = New uriconvertRIMPL ();
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);
}
iii. Output: Before: http:///somemodel.ecore/
After: platform: /resource/project/somemodel.ecore/
Before: http://somemodel.ecore/#hello
After: platform: /resource/project/SOMEMEMODEL.ECORE/# Hello
b) resource management:
i. Description: Resource is an abstraction used to store model data. ResourceSet is used to manage Resource. When we need to create a new Resource, we call the Createresource () method on the ResourceSet, which forwards the request to the ResourceFactory, which is finally created by ResourceFactory.
ii. model:
Create
Manager
ResourceFactory
Resourceset
Resource
Resource
Resource
iii. Resources creation:
1. code:
Public void write (string filename) throws oewception {
Resource.factory.registry.instance.GetextensionTofactoryMap ().
PUT ("*", new xmlresourcefactoryImpl ());
ResourceSet ResourceSet = New ResourceSetiMPL ();
Uri fileuri = uri.createuri ("supplier.po");
Resource resource = resourceserset.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.getRDERS (). Add (po1);
Sup.getRDERS (). Add (po2);
Cus1.getorders (). Add (po1);
Cus1.getorders (). Add (po2);
Resource.getContents (). Add (SUP);
Resource.save (null);
}
2. Result:
XML Version = "1.0" encoding = "ascii"?>
PO: Supplier>
3. Description: Here you demonstrate how to add a single value, multi-value properties, including, and non-inclusive references. Blue indicates that the reference is included, and the reference will be added as a child node in the target file. Red means non-inclusive reference, non-inclusion references will be added as attributes in the target file.
iv. Resource Read:
1. code:
Public EOBJECT (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 ();
}
}
2. Description: The program must run correctly after the plugin is running, because the association of resources is completed during the initialization of the plugin . Fragment is a path expression similar to XPath syntax, like "@customers.0", etc. c) resource management implementation
i. Description: EMF uses XML and XMI to store resources, during storage and reading, we can It is passed to a HashMap to customize the process of storage and read.
5. EMF.EDIT-Adapter
a) Description: We can use three ways to add additional listeners to the object.
b) direct:
i. code:
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 homeadapter ());
...
}
ii. Description: This way you need to get the EADAPTERS list of the model object, and add them directly.
c) extended AdapterFactoryImpl:
i. code:
Public Class Some
ADA
Pter Extends
ADA
PteriMPL {
Public void notifychanged (notification notification) {
...
}
Public Boolean isadapterfortype (Object Type) {
Return Type == SomeAdapter.class;
}
}
Public class homeadapterfactory 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);
...
}
II. Description: This method does not directly operate the list of listeners of the object, but through AdapterFactory's Adapt () method . Inside this method, he will first traverse the EADAPTERS list of the model object to see if there is a support corresponding type adapter existence. If not, he calls the createAdapter () method to create a new adapter and add it to the EADAPTERS list. .
d) PoadapterFactory :-> Extended model
i. code:
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);
...
}
ii. Description: This method is similar to the second similar, and the different places is that he does not implement the createadapter () method, but Enable CREATEXYZADAPTER () that creates a particular type. This is because in the internal, his CreateAdapter () method is in accordance with the incoming object, then the CreatexyZADAPTER () method of creating the corresponding type is called based on the result of the match. In addition, it should be noted here that although we don't have CreateusAddressadapter (), it is a creteaddressadapter () method, but it is successful. This is because the CreateusAddressAdapter () method returns empty in PoadapterFactory, which will cause the windowPreterFactory to call usaddressAdapter () method according to the inheritance chain.
e) registration adapterfactory
i. Description: The above ways need us to explicitly adapt adaptation, in general, us more The usual approach is to register to the RESOURCESET in the model. This allows the system yourself to add a suitable Adapter when needed. Since it is necessary to rely on the existing resultset instance, you need to do it after the plugin is started. ii. code:
ResourceSet RS = ...
rs.getadapterfactories (). add (new someadapterfactory);
/ / Then when needed
Ecoreutil.getRegisteredAdapter (address, someadapter.class);
In the GetRegisteredAdapter (), he will find the RESOURESET through the model instance and then obtain AdapterFactory that supports the corresponding type by this resourceset, then call the factory Adapt () method.
f) Optimize the event handle:
i. Description: When the property modifies the event, and when the type of attribute is the basic type, we can use the following two Way optimizes the acquisition of the notification content.
ii. code:
Assume that we monitor 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;
}
}
Description: We can also determine which property is modified by calling the Notification.getFeature () method, then use the IF-ELSE method. But the advantage of the above means is to be more lightweight. Another point is that when we get the property modified value, we call a type of getoldintValue () method, the reason is that when the attribute is the basic type, then the EMF will only go inside when assembling the Notification instance. Fill in the basic type, therefore, if we directly call the airful DETDVALUE () directly, he will need to encapsulate the basic type by the corresponding Wrapper class, which will lead to performance.
6. EMF.EDIT-Commands Reserved a) Description: Due to the model in EMF The modification is done with Command, so we need a method for customization of Command. Due to the EMF.EDIT, when the model is needed, he will be completed by the corresponding XYZITEMPROVIDER CREATEXXXCOMMAND (), and in general, XYZITEMPROVIDER calls his parent class ItemProvideradapter CREATEXXXCOMMAND (), so when we need When you change this default behavior, we only need to overload this createxxxCommand () inside the corresponding XYZITEMPROVIDER.
b) code:
Public class xyzitemprovider extens itemprovideradapter {
Public Command CreatexxxCommand (EditingDomain Domain, EOBJECT OWNER,
ESTRUCTURALARAL FEATURE, Object value) {
Return New MyxxxCommand (Domain, Owner, Feature, Value) {};
}
Public Command CreateYycoMad (EditingDomain Domain, EOBJECT OWNER,
ESTRUCTURALARAL FEATURE, Object value) {
Return New MYYYYCOMMAND (Domain, Owner, Feature, Value) {};
}
}
Public class myxxxcommand extends xxxcommand {
Public MyCommand (EditingDomain Domain, EOBJECT OWNER, ESTRUCTURALARURE 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,
ESTRUCTURALARAL FEATURE, Object value) {
this.domain = Domain;
...
Append (New Zzzcommand (Domain, Owner, Feature, Value);
}
Public void eXcute () {
Super.excute ();
...;
Appendandexcute (New Aaacommand ());
}
}
Description: We extend an existing XXXCommand in MyxxxCommand, so we can save the properties by calling the super () method, and in this case, we overload the doexcute () method. In myYyyCommand, because we extend CompoundComand, we need to save these variables. CompoundCommand refers to, in this command, multiple commands can be combined, which is completed by append (). In the MyYyyCommand class, we overloaded the Excute () method, and call super.excute () to perform the command already append in the queue, after we need to add a command, we can use the appendandexcute () method. 7. EMF.EDITOR - editor custom:
a) root node display: Modify the CreatePages () method of Editor.
i. 图 -:
ii. before code:
Public void createpages () {
...
SelectionViewer.setInput (EditingDomain.getResource ()); ViewerPane.SetTitle (EditingDomain.getResourceSet ());
...
}
iii. :
iv. The code:
Public void createpages () {
...
ResourceSet RS = (resource) EditingDomain.getResourceSet ();
Resource res = rs.getResources (). Get (0);
SelectionViewer.setInput (res);
ViewerPane.SetTitle (RES);
...
}
b) Display: Modify the corresponding XXXITEMPROVIDER's getChildRenfeatures () method.
i. 图 -:
II. before code: 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;
}
iii. :
iv. The code:
Public Collection getChildrenfeatures (Object object) {
IF (childrenfeatures == null) {
Super.getChildrenfeatures (Object); Childrenfeatures.Add (POPAGKAGE.EINSTANCE.GETPURCHASEORDER_ITEMS ()); //childrenfeatures.add (popackage.einstance.getpurchaseORDER_SHIPTO ());
}
Return Childrenfeatures;
}
c) attribute Edit: Modify the corresponding XYZITEMPROVIPTORS () method.
i. 图 -:
ii. before code:
Public List getPropertyDescriptors (Object Object) {
IF (itempropertydescriptors == null) {
Super.getPropertyDescriptors (Object);
AddcommentPropertyDescriptor (Object);
AddorderDatePropertyDescriptor (Object);
AddStatusPropertyDescriptor (Object);
AddtotalamountPropertyDescriptor (Object);
AddCustomerPropertyDescriptor (Object);
}
Return ItemPropertyDescriptors;
iii. :
iv. The code:
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 feature) {
AddressItemProvider Pro = (AddressItemprovider) AdapterFactory.adapt (
Address, IIITEMPROPERTYSOURCE.CLASS;
List ads = pro.getPropertyDescriptors (address);
Iterator it = ads.Itemrator (); ore.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);
}
});
}
}
d) custom Editor
i. Description:
1. Download a lot of Viewer in both in EMF.Editor, the initialization of these Viewers is implemented in the createpages () method, so if We want to customize these Viewer types and behaviors, and we modify this method.
2. When you select a node in Outline, you can trigger the handlecontentoutLinselection () method, we can face the dynamics of Viewer here. Behavior is customized.
3. "" "" "" "" "" "" "", "" "" "" "" "" "" "" "" ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, There is no ITABLETEMLABELPROVIDER, so he cannot return different text based on columns, so we can make XYZITEMProvider implement ITABLETEMLabelProvider, and we need to add a line in the constructor of Emf.edit PoItemProvideradApterFactory. Public poitemprovideradapterfactory () {
SupportedTypes.Add (istructuredItemContentProvider.class);
SupportedTypes.Add (ItreeItemContentProvider.class);
SupportedTypes.Add (IIITEMPROPERTYSOURCE.CLASS);
SupportedTypes.Add (IEditingDomainItemProvider.class);
SupportTypes.Add (IIITEMLabelProvider.class);
SupportedTypes.Add (ItableItemLabelProvider.class);
}