SlideShare a Scribd company logo
Christian W. Damus, Kenn Hussey, Ed Merks and Dave Steinberg IBM Rational Software Ottawa and Toronto, Canada EMF, EMFT, and MDT Projects Effective Use of the Eclipse Modeling Framework https://w3-03.ibm.com/legal/ipl/iplsite.nsf/pages/wtts-trademarks+home
Part 1: Introduction to the Eclipse Modeling Framework
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
EMF Demo Quickly generate a working graphical editor to create and manipulate instances of a UML model
What is EMF? A modeling & data integration framework Exploits the facilities offered in Eclipse to… Generate code without losing user customizations (merge) Automate important tasks (such as registering the runtime information) Improve extensibility Provide a UI layer What is an EMF “model”? Specification of your application’s data Object attributes Relationships (associations) between objects Operations available on each object Simple constraints (eg. cardinality) on objects and relationships Essentially it represents the class diagram of the application
What does EMF Provide? From a model specification, EMF can generate efficient, correct, and easily customizable implementation code Out of the box, EMF provides support for Java ™  interfaces UML XML Schema EMF converts your models to Ecore (EMF metamodel) Tooling support within the Eclipse framework (UI, headless mode, Ant and standalone), including support for generating Eclipse-based and RCP editors Reflective API and dynamic model definition Persistence API with out of box support for XML/XMI (de)serialization of instances of a model And much more….
Why EMF? EMF is middle ground in the modeling vs. programming worlds Focus is on class diagram subset of UML modeling (object model) Transforms models into Java code Provides the infrastructure to use models effectively in your application Very low cost of entry  EMF is free and open source Full scale graphical modeling tool not required Reuses your knowledge of UML, XML Schema, or Java It’s real, proven technology (since 2002)
EMF History First version was released in June, 2002 Originally based on MOF (Meta Object Facility) From OMG (Object Management Group) Abstract language and framework for specifying, constructing, and managing technology neutral metamodels EMF evolved based on experience supporting a large set of tools Efficient Java implementation of a practical subset of the MOF API 2003: EMOF defined (Essential MOF) Part of OMG’s MOF 2 specification; UML2 based EMF is approximately the same functionality Significant contributor to the spec; adapting to it
Who is Using EMF Today? Eclipse projects Foundation for the Modeling Project: Graphical Modeling Framework (GMF), EMF Ontology Definition Metamodel (EODM), UML2… Other uses: Web Tools Platform (WTP), Test and Performance Tools Platform (TPTP), Business Intelligence and Reporting Tools (BIRT), Data Tools Platform (DTP), Visual Editor (VE)… Commercial offerings IBM, Borland, Oracle, Omondo, Versata, MetaMatrix, Bosch, Ensemble… Applied sciences Darmstadt University of Technology, Mayo Clinic College of Medicine, European Space Agency… Large open source community Over 1,000,000 download requests in 2006
EMF at IBM Pervasive usage across product lines IBM ®  Rational ®  Software Architect IBM Rational Application Developer for WebSphere Software IBM WebSphere ®  Integration Developer IBM WebSphere Application Server IBM Lotus ®  Workplace Emerging technology projects: alphaWorks ® Emfatic Language for EMF Development (http://www.alphaworks.ibm.com/tech/emfatic) Model Transformation Framework (http://www.alphaworks.ibm.com/tech/mtf) XML Forms Generator (http://www.alphaworks.ibm.com/tech/xfg)
What Have People Said About EMF? EMF represents the  core subset  that's left when the non-essentials are eliminated. It represents a  rock solid foundation  upon which the more ambitious extensions of UML and MDA can be built. –  Vlad Varnica, OMONDO Business Development Director, 2002 EMF  provides the glue between the modeling and programming worlds , offering an infrastructure to use models effectively in code by integrating UML, XML and Java. EMF thus fits well into [the] Model-Driven Development approach, and is  critically important for Model-Driven Architecture , which underpins service-oriented architectures [SOA].  –  Jason Bloomberg, Senior analyst for XML & Web services, ZapThink, 2003 EMF was chosen because it (a) provides a  lightweight, pragmatic approach  to modeling with  very low entry cost  and is thus suitable for rapid prototyping, (b) unifies key technologies such as Java and XML, and (c) integrates well into Eclipse. –  Bruch, Bockisch, Schäefer, Mezini, Darmstadt Univ. of Technology, 2005 [As] a consultant with fiduciary responsibility to my customers, [...] given the  enormous traction  that Eclipse has gathered, we have to view the EMF metadata management framework as the  de facto standard . –  David Frankel, as seen in Business Process Trends, March 2005
Creating the Ecore Model Representing the modeled domain in Ecore is the first step in using EMF Ecore can be created  Directly using the EMF editors Through a graphical UI provided by external contributions By converting a model specification for which a Model Importer is available Model Importers available in EMF Java Interfaces UML models expressed in Rational Rose ®  files XML Schema Choose the one matching your perspective or skills
Model Importers Available in EMF Java Interfaces public interface  PurchaseOrder { String  getShipTo (); void setShipTo(String value); String  getBillTo (); void setBillTo(String value); List<Item>  getItems (); } public interface  Item { String  getProductName (); void setProductName(String value); int  getQuantity (); void setQuantity(int value) float  getPrice (); void setPrice(float value); }
Model Importers Available in EMF UML Class Diagram
Model Importers Available in EMF XML Schema <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <xsd:schema xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; targetNamespace=&quot;http://www.example.com/SimplePO&quot; xmlns:PO=&quot;http://www.example.com/SimplePO&quot;> <xsd:complexType name=&quot; PurchaseOrder &quot;> <xsd:sequence> <xsd:element name=&quot; shipTo &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; billTo &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; items &quot;  type=&quot;PO:Item&quot;  minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;/> </xsd:sequence> </xsd:complexType> <xsd:complexType name=&quot;Item&quot;> <xsd:sequence> <xsd:element name=&quot; productName &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; quantity &quot; type=&quot;xsd:int&quot;/> <xsd:element name=&quot; price &quot; type=&quot;xsd:float&quot;/> </xsd:sequence> </xsd:complexType> </xsd:schema>
Unifying Java, XML and UML Technologies The Model Importers available in EMF were carefully chosen to integrate today’s most important technologies All three forms provide the same information Different visualization/representation The application’s “model” of the structure From a model definition, EMF can generate Java implementation code, including UI XML Schemas Eclipse projects and plug-in
Typical EMF Usage Scenario Create an Ecore model that represents the domain you are working on Import UML (e.g. Rose .mdl file) Import XML Schema Import annotated Java interfaces Create Ecore model directly using EMF's Ecore editor or a graphical editor Generate Java code for model Prime the model with instance data using generated EMF model editor Iteratively refine model (and regenerate code) and develop Java application You will use the EMF generated code to implement the use cases of your application Optionally, use EMF.Edit to build customized user interface
EMF and Java 5.0 EMF 2.3 exploits the capabilities of Java 5.0 Generics  Typesafe enums Annotations Enhanced for loop Autoboxing EMF 2.3 provides a 5.0-targeted runtime that can only be run on a Java 5.0 or later VM The code generator can also produce application code that runs on a 1.4 VM against the EMF 2.2.x runtime This is a recognition that Java 5.0 is the way forward, but the transition need not be painful for the user
EMF and Java 5.0 Want to know more about Java 5.0 and EMF? Modeling Generics with Ecore Tuesday, 11:10 am Grand Ballroom D Java 5: A Developer’s Experience Thursday, 10:10 am Room 203-204
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
EMF Architecture EMF Runtime EMF Tools Core Edit Codegen Model Editor Application Generates Eclipse Platform
EMF Components EMF Core Ecore metamodel Model change notification & validation Persistence and serialization  Reflection API  Runtime support for generated models EMF Edit Helps integrate models with a rich user interface Used to build editors and viewers for your model Includes default reflective model editor EMF Codegen Code generator for core and edit based components Extensible model importer/exporter framework
EMF Tools: Model Import and Generation Generator Features: Customizable JSP-like templates (JET) JDT-integrated, command-line, or Ant Fully supports regeneration and merge I M P O R T GENERATE Ecore Model UML XML Schema Java model Java model Java edit Java editor* * Eclipse IDE-integrated or RCP-based
EMF Model Importers UML Rational Rose .mdl file Eclipse UML2 project provides importer for .uml2 Annotated Java Java interfaces representing modeled classes Javadoc annotations using @model tags to express model properties not captured by method declarations Lowest cost approach XML Schema Describes the data of the modeled domain Provides richer description of the data, which EMF exploits Ecore model  (*.ecore file) Just creates the generator model (discussed later) Also handles EMOF (*.emof)
Ecore Model Creation An Ecore model is created within an Eclipse project via a wizard Input: one of the model specifications from the previous slide Output: modelname.ecore Ecore model file in XMI format Canonical form of the model modelname.genmodel A “generator model” for specifying generator options Contains decorators for Ecore model elements, providing details that would otherwise pollute the model (e.g. target directories for code generation) EMF code generator is an EMF .genmodel editor Automatically kept in synch with .ecore file
Ecore Model Editor A generated (and customized) EMF editor for the Ecore model Create, delete, etc. model elements (EClass, EAttribute, EReference, etc.) using pop-up actions in the editor's tree Set names, etc. in the Properties view
Ecore Model Editor A graphical editor is a better approach GMF Ecore Diagram Example (http://www.eclipse.org/gmf/) Omondo EclipseUML (http://www.omondo.com/)
EMF Generator Similar layout to Ecore model editor Automatically keeps in synch with .ecore changes Generate code with pop-up menu actions Generate Model Code Generate Edit Code Generate Editor Code Generate Test Code Generate All Code generation options in Properties view Generator > Reload to reload .genmodel and .ecore files from original model form
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
The Ecore (Meta) Model Ecore is EMF's model of a model Also called a  “metamodel” Persistent representation is XMI
The Ecore Metamodel
Partial List of Ecore Data Types Ecore data types are serializable and custom data types are supported java.lang.Float EFloatObject java.lang.Object EJavaObject java.lang.Boolean EBooleanObject byte[ ] EByteArray java.lang.String EString float EFloat char EChar boolean EBoolean Java Primitive Type or Class Ecore Data Type
Ecore Model for Purchase Orders is represented in Ecore as
Purchase Order Ecore XMI Alternate serialization format is EMOF (Essential MOF) XMI Part of OMG Meta Object Facility (MOF) 2.0 standard (http://www.omg.org/docs/ptc/04-10-15.pdf) <eClassifiers xsi:type=&quot;ecore:EClass&quot; name=&quot; PurchaseOrder &quot;> <eReferences name=&quot; items &quot; eType=&quot;#//Item&quot;  upperBound=&quot;-1&quot; containment=&quot;true&quot;/> <eAttributes name=&quot; shipTo &quot;  eType=&quot;ecore:EDataType http:...Ecore#//EString&quot;/> <eAttributes name=&quot; billTo &quot;  eType=&quot;ecore:EDataType http:...Ecore#//EString&quot;/> </eClassifiers>
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
Code Generation EMF framework is lightweight Generated code is clean, simple, efficient EMF can generate Model implementation UI-independent edit support Editor and views for Eclipse IDE-integrated or RCP application JUnit test skeletons Manifests, plug-in classes, properties, icons, etc.
Generated Model Code Interface and implementation for each modeled class Includes get/set accessors for attributes and references Usage example public interface  PurchaseOrder  extends EObject { String  getShipTo (); void  setShipTo (String value); String  getBillTo (); void  setBillTo (String value); EList<Item>  getItems (); } order .getItems().add( item );
Generated Model Code Factory to create instances of model objects Package class provides access to metadata Also generated: switch utility, adapter factory base, validator, custom resource, XML processor POFactory factory =  POFactory.eINSTANCE ; PurchaseOrder order =  factory .createPurchaseOrder(); POPackage poPackage =  POPackage.eINSTANCE ; EClass itemClass = poPackage. getItem (); //or POPackage.Literals.ITEM EAttribute priceAttr = poPackage. getItem_Price (); //or itemClass.getEStructuralFeature( POPackage.ITEM__PRICE ) //or POPackage.Literals.ITEM__PRICE
Generated Edit/Editor Code Viewing/editing code divided into two parts UI-independent code  Item providers (adapters) Item provider adapter factory UI-dependent code Model creation wizard Editor Action bar contributor Advisor (RCP) By default each part is placed in a separate Eclipse plug-in
Java 5.0 Constructs For a new model, EMF 2.3 targets the compiler compliance level specified by the containing project (or the workspace default) To generate code with Java 5.0 constructs for an existing model, use the “Compliance Level” property on the GenModel
Summary of Generated Artifacts Model Interfaces and classes Type-safe enumerations Package (metadata) Factory Switch utility Adapter factory base Validator Custom resource XML Processor Edit (UI independent) Item providers Item provider adapter factory Editor Model Wizard Editor Action bar contributor Advisor (RCP) Tests Test cases Test suite Stand-alone example Manifests, plug-in classes, properties, icons...
Regeneration and Merge Hand-written code can be added to generated code and preserved during regeneration This merge capability has an Eclipse dependency, so is not available standalone All generated classes, interfaces, methods and fields include @generated marker in their Javadoc To replace generated code: Remove @generated marker Or include additional text, e.g. @generated NOT Methods without @generated marker are left alone during regeneration
Regeneration and Merge Extend (vs. replace) generated method through redirection Append “Gen” suffix to the generated method's name /** * <!-- begin-user-doc --> * <!-- end-user-doc --> *  @generated */ public String getName Gen () { return name; } public String  getName () { return format(getNameGen()); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> *  @generated */ public String  getName () { return name; }
The Code Generation Process Java Code Model Importer JET Simplified version UML Java Model ? XML Schema GenModel Ecore
The Code Generation Process Java Code Merged Java Code Model Importer JET JMerge Generated Java Code Full version UML Java Model ? XML Schema GenModel Ecore
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
EMF Runtime Persistence and serialization of model data Proxy resolution and demand load Automatic notification of model changes Bi-directional reference handshaking Dynamic object access through a reflective API Runtime environments Eclipse Full IDE RCP Standalone Java
Persistence and Serialization Serialized data is referred to as a resource Data can be spread out among a number of resources in a resource set One resource is loaded at a time, even if it has references to objects in other resources in the resource set Proxies exist for objects in other resources Lazy or demand loading of other resources as needed A resource can be unloaded
Resource Set Context for multiple resources that may have references among them Usually just an instance of ResourceSetImpl, or a customized subclass Provides factory method for creating new resources in the set: Also provides access to the registries, URI converter, and default load options for the set ResourceSet  rs = new  ResourceSetImpl (); URI uri = URI.createFileURI(&quot;C:/data/po.xml&quot;); Resource resource = rs. createResource (uri);
Resource Factory Registry Returns a resource factory for a given type of resource Based on the URI scheme or filename extension Determines the type of resource, hence format for save/load For models created from XML Schema, the generated custom resource factory implementation should be registered to ensure schema-conformant serialization When running as a plug-in under Eclipse, EMF provides an extension point for registering resource factories Generated plugin.xml registers generated resource factory against a package specific extension (e.g. “po”) Global registry: Resource.Factory.Registry.INSTANCE Consulted if no registered resource factory found locally Resource.Factory.Registry  reg = rs. getResourceFactoryRegistry (); reg. getExtensionToFactoryMap ().put(&quot; xml &quot;, new  XMLResourceFactoryImpl ());
Package Registry Returns the package identified by a given namespace URI Used during loading to access the factory for creating instances Global registry: EPackage.Registry.INSTANCE Consulted if no registered package found locally Running in Eclipse, EMF provides an extension point for globally registering generated packages Even standalone, a package automatically registers itself when accessed: EPackage.Registry  registry = rs. getPackageRegistry (); registry.put( POPackage.eNS_URI ,  POPackage.eINSTANCE ); POPackage   poPackage =  POPackage.eINSTANCE;
Resource Container for objects that are to be persisted together Convert to and from persistent form via save() and load() Access contents of resource via getContents() EMF provides XMLResource implementation Other, customized XML resource implementations, provided, too (e.g. XMI, Ecore, EMOF) URI uri = URI.createFileURI(&quot;C:/data/po.xml&quot;); Resource resource = rs.createResource(uri); resource. getContents ().add(p1); resource. save (null); <PurchaseOrder> <shipTo>John Doe</shipTo> <next>p2.xml#p2</next> </PurchaseOrder>
Proxy Resolution and Demand Load PurchaseOrder p2 =   p1. getNext (); p1 p1.xml next p2 p2.xml proxyURI=“ p2.xml #p2” next proxyURI=“p2.xml#p2” next <PurchaseOrder> <shipTo>John Doe</shipTo> <next> p2.xml#p2 </next> </PurchaseOrder> p1.xml
Model Change Notification Every EMF object is also a Notifier Send notification whenever an attribute or reference is changed EMF objects can be “observed” in order to update views and dependent objects Adapter  poObserver = ... purchaseOrder. eAdapters ().add(poObserver);
Model Change Notification Observers or listeners in EMF are called adapters An adapter can also extend class behavior without subclassing For this reason they are typically added using an AdapterFactory PurchaseOrder purchaseOrder = ... AdapterFactory  somePOAdapterFactory = ... Object poExtensionType = ... if (somePOAdapterFactory. isFactoryForType (poExtensiontype)) { Adapter  poAdapter = somePOAdapterFactory. adapt (purchaseOrder, poExtensionType); ... }
Model Change Notification Efficient notification in “set” methods Checks for listeners before creating and sending notification public String getShipTo() { return shipTo; } public void setShipTo(String newShipTo) { String oldShipTo = shipTo; shipTo = newShipTo; if (eNotificationRequired()) eNotify(new ENotificationImpl(this, ... ); }
Bidirectional Reference Handshaking public interface  PurchaseOrder { PurchaseOrder  getNext (); void  setNext (PurchaseOrder value); PurchaseOrder  getPrevious (); void  setPrevious (PurchaseOrder value); } Invariant imposed by the bidirectional reference:  po.getNext().getPrevious() == po
Bidirectional Reference Handshaking p1. setNext (p3); p2 p1 p2 p3 previous next next previous next previous next previous change notification
Bidirectional Reference Handshaking This multi-step procedure is implemented using InternalEObject methods: eInverseRemove() eInverseAdd() Framework list implementations and generated setters directly invoke them on target objects as needed Notifications are accumulated using a NotificationChain and fired off at the end They are not used to implement the handshaking
Reflection All EMF classes implement interface EObject Provides an efficient API for manipulating objects reflectively Used by the framework (e.g., serialization/deserialization, copy utility, generic editing commands, etc.) Also key to integrating tools and applications built using EMF public interface  EObject { EClass  eClass (); Object  eGet (EStructuralFeature sf); void  eSet (EStructuralFeature sf, Object val); ... }
Reflection Example Setting an attribute using generated API: Using reflective API: PurchaseOrder po = ... po. setBillTo (&quot;123 Elm St.&quot;); EObject po = ... EClass poClass = po.eClass(); po. eSet (poClass.getEStructuralFeature(&quot;billTo&quot;), &quot;123 Elm St.&quot;);
Reflective Performance Efficient generated switch-based implementation of reflective methods public Object  eGet (int featureID, ...) { switch  (featureID) { case POPackage.PURCHASE_ORDER__SHIP_TO: return  getShipTo (); case POPackage.PURCHASE_ORDER__BILL_TO: return  getBillTo (); ... } }
Reflection Benefits Reflection allows generic access to any EMF model Similar to Java’s introspection capability Every EObject (that is, every EMF object) implements the reflection API An integrator need only know your model! A generic EMF model editor uses the reflection API Can be used to edit any EMF model
Dynamic EMF Ecore models can be defined dynamically in memory No generated code required Dynamic implementation of reflective EObject API provides same runtime behavior as generated code Also supports dynamic subclasses of generated classes All EMF model instances, whether generated or dynamic, are treated the same by the framework A dynamic Ecore model can be defined by Instantiating model elements with the Ecore API Loading from a .ecore file
Dynamic EMF Example Model definition using the Ecore API EPackage poPackage = EcoreFactory.eINSTANCE. createEPackage (); poPackage. setName (&quot;po&quot;); poPackage. setNsURI (&quot;http://www.example.com/PurchaseOrder&quot;);     EClass poClass = EcoreFactory.eINSTANCE. createEClass (); poClass. setName (&quot;PurchaseOrder&quot;); poPackage. getEClassifiers ().add(poClass);    EAttribute billTo = EcoreFactory.eINSTANCE. createEAttribute (); billTo. setName (&quot;billTo&quot;); billTo. setEType (EcorePackage.eINSTANCE. getEString ()); poClass. getEStructuralFeatures ().add(billTo); ... EObject po = EcoreUtil.create(poClass); po.eSet(billTo,&quot;123 Elm St.&quot;);
XML Processor Simplified API for loading and saving XML Handles resource set, registries, etc. under the covers Can automatically create a dynamic Ecore representation of a schema Load/save instance documents without generating code Manipulate the objects using reflective EObject API  URI schemaURI = ... String instanceFileName = ... XMLProcessor processor =  new XMLProcessor (schemaURI); Resource resource = processor. load (instanceFileName, null); EObject documentRoot = resource.getContents.get(0);
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
Recording Changes EMF provides facilities for recording the changes made to instances of an Ecore model Change Model An EMF model for representing changes to objects Directly references affected objects Includes “apply changes” capability Change Recorder EMF adapter Monitors objects to produce a change description (an instance of the change model)
Change Model
Change Recorder Can be attached to EObjects, Resources, and ResourceSets Monitors changes to the objects and their contents trees Produces a description of the changes needed to return to the original state (a reverse delta) Result: a change description with one change, setting billTo to “123 Elm St.” PurchaseOrder order = ... order.setBillTo(&quot;123 Elm St.&quot;); ChangeRecorder recorder = new ChangeRecorder(); recorder. beginRecording (Collections.singleton(order)); order.setBillTo(&quot;456 Cherry St.&quot;); ChangeDescription change = recorder. endRecording ();
Applying Changes Given a change description, the change can be applied: ChangeDescription.apply() consumes the changes, leaving the description empty ChangeDescription.applyAndReverse() reverses the changes, leaving a description of the changes originally made (the forward delta) The model is always left in an appropriate state for applying the resulting change description
Example: Transaction Capability If any part of the transaction fails, undo the changes ChangeRecorder changeRecorder = new ChangeRecorder(resourceSet); try { // modifications within resource set } catch (Exception e) { changeRecorder. endRecording (). apply (); }
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
Validation Framework Model objects validated by external EValidator Detailed results accumulated as Diagnostics Essentially a non-Eclipse equivalent to IStatus Records severity, source plug-in ID, status code, message, other arbitrary data, and nested children  public interface  Evalidator { boolean  validate (EObject eObject, DiagnosticChain diagnostics, Map Context); boolean  validate (EClass eClass, EOjbect eObject, DiagnosticChain, diagnostics, Map context); boolean  validate (EDataType eDataType, Object value, DiagnosticChain diagnostics, Map context); ... }
Invariants and Constraints Invariant Defined directly on the class, as an operation with <<inv>> stereotype Stronger statement about validity than a constraint Constraint Externally defined for the class via a method on the validator
Generated EValidator Implementations Generated for each package that defines invariants or constraints Dispatches validation to type-specific methods For classes, a validate method is called for each invariant and constraint Method body must be hand coded for invariants and named constraints
Schema-Based Constraints In XML Schema, named constraints are defined via annotations: Also, constraints can be defined as facets on simple types, and no additional coding is required Constraint method implementation generated <xsd:annotation> <xsd:appinfo source=&quot;http://www.eclipse.org/emf/2002/Ecore&quot;  ecore:key=&quot;constraints&quot;>VolumeDiscount</xsd:appinfo> </xsd:annotation> <xsd:simpleType name=&quot;SKU&quot;> <xsd:restriction base=&quot;xsd:string&quot;> <xsd:pattern value=&quot;\d{3}-[A-Z]{2}&quot;/> </xsd:restriction> </xsd:simpleType>
Framework EValidator Implementations EObjectValidator validates basic EObject constraints: Multiplicities are respected Proxies resolve All referenced objects are contained in a resource Data type values are valid Used as base of generated validators and directly for packages without additional constraints defined
Framework EValidator Implementations Diagnostician walks a containment tree of model objects, dispatching to package-specific validators Diagnostician.validate() is the usual entry point Obtains validators from its EValidator.Registry Diagnostician   validator =  Diagnostician.INSTANCE ; Diagnostic diagnostic = validator. validate (order); if (diagnostic.getSeverity() == Diagnostic.ERROR) { // handle error } for (Diagnostic child : diagnostic.getChildren()) { // handle child diagnostic }
Agenda EMF in a Nutshell  EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
Summary EMF is low-cost modeling for the Java mainstream Boosts productivity and facilitates integration Mixes modeling with programming to maximize the effectiveness of both
Summary EMF provides… A metamodel (Ecore) with which your domain model can be specified Your model can be created from UML, XML Schema or annotated Java interfaces Generated Java code Efficient and straightforward  Code customization preserved Persistence and Serialization Resource-based serialization Proxy resolution and demand loading Default resource implementation is XMI (XML metadata interchange), but can be overridden
Summary EMF provides… Model change notification is built in Just add adapters (observers) where needed Reflection and dynamic EMF Full introspection capability Simple change recording and roll-back Extensible validation framework Standalone runtime support A UI-independent layer for viewing and editing modeled data (EMF.Edit)
Part 2: Advanced Features of the Eclipse Modeling Framework
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Working with Resources and ResourceSets Working with proxies Identifying proxies Using the Validation Framework to detect unresolved proxies Using “fragment queries” to handle unresolved proxies Cross-Resource Containment Inverse References Resource Tips & Tricks Unloading Tracking modification Am I loading something?
Persistence and Serialization Review Serialized data is referred to as a resource Data can be spread out among a number of resources in a resource set One resource is loaded at a time, even if it has references to objects in other resources in the resource set Proxies exist for objects in other resources Lazy or demand loading of other resources as needed A resource can be unloaded
Identifying Proxies In some scenarios it may be important to know up-front what are the proxies referenced by a given object Check whether the user has everything that will be necessary to load the model Extract missing resources from the repository Decide whether loading a specific object is a long or short operation org.eclipse.emf.ecore.util.EcoreUtil.ProxyCrossReferencer A CrossReferencer that finds proxies without resolving them For each object in a given context (resource, resource set, EObject, collection), checks if the referenced objects are in the same resource or not
Going Deeper: EcoreUtil’s CrossReferencers Utility classes that find “uses” of an object Also the data structures that hold the objects they find A CrossReferecer is a java.util.Map On each Map.Entry Key: reference target Value: list of EStructuralFeature.Setting with all the source  object-feature pairs referencing the keyed target
Going Deeper: EStructuralFeature.Setting Interface that represents the value held by a feature of an EObject Exposes all the feature-related methods of EObject eGet, eSet, eIsSet, and eUnset
Going Deeper: Types of Reference Containment Reference Has an “implicit” opposite (eObject.eContainer()) Container Reference An explicit reference defined as the opposite of a containment reference Cross-Reference May or may not have an opposite Any reference can refer to an EObject located in either the same or different resource
EcoreUtil.ProxyCrossReferencer public static void printProxiesDetails(ResourceSet  resourceSet ) { int counter = 0; Map<EObject, Collection<EStructuralFeature.Setting>> map = ProxyCrossReferencer .find(resourceSet); for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> entry : map.entrySet()) { EObject  proxyEObject  = entry. getKey (); System.out.println (&quot;&quot; + ++counter + &quot;. &quot; + EcoreUtil.getURI(proxyEObject)); System.out.println (&quot;Is Proxy: &quot; + proxyEObject.eIsProxy()); for (EStructuralFeature.Setting  setting  : entry. getValue ()) { System.out.println (&quot;\tFeature: &quot; + setting. getEStructuralFeature ().getName()); EObject eObject = setting. getEObject (); EStructuralFeature nameFeature = eObject.eClass().getEStructuralFeature(&quot;name&quot;); if (nameFeature != null) { System.out.println (&quot;\tEObject.getName(): &quot; + eObject.eGet(nameFeature)); } } }  } 1. uri3.xmi#/0 Is Proxy: true Feature: home EObject.getName(): john
Validating Proxies The validation framework can be used to validate proxies The EObjectValidator checks if all the referenced objects of a given EObject are resolved The proxy references are resolved during the validation If a proxy is broken, the validation produces a Diagnostic with EObjectValidator. EOBJECT__EVERY_PROXY_RESOLVES  as its error code
Validating Proxies public static void validateProxies(EObject eObject) { Diagnostic  diagnostic  =  Diagnostician .INSTANCE. validate (eObject); if (diagnostic.getSeverity() == Diagnostic.ERROR) { if ( hasEveryProxyResolvesCode (diagnostic)) { System.out.println (&quot;Broken proxies found!&quot;); return; } } System.out.println (&quot;Proxies are fine.&quot;); } public static boolean  hasEveryProxyResolvesCode (Diagnostic diagnostic) { if (diagnostic. getCode () == EObjectValidator. EOBJECT__EVERY_PROXY_RESOLVES ) return true; for (Diagnostic childDiagnostic : diagnostic.getChildren()) { return  hasEveryProxyResolvesCode (childDiagnostic); } return false; }
Handling Broken Proxies Your application can provide a mechanism to handle broken proxies by Reporting the error to the user Avoiding use of the object(s) that could not be resolved Recovering the missing object(s) EMF doesn’t provide such a mechanism but provides hooks to help you implement one Fragment query capability is one of these hooks
Stepping Back: Uniform Resource Identifier (URI) A formatted string that serves as an identifier for a resource Specification: Definition: http://www.ietf.org/rfc/rfc1630.txt Generic Syntax: http://www.ietf.org/rfc/rfc2396.txt Syntax: Generic [ scheme : ] scheme-specific-part [ # fragment ] Hierarchical [ scheme : ][ // authority ][ path ][ ? query ][ # fragment ] Used in EMF to identify a resource, an object in a resource, or an Ecore package (namespace URI)
Fragment Queries The idea is to “decorate” the fragment portion of a URI with details that further describe the referenced object The description can be used by a service to locate the object or to enrich an error message to be presented to the user Query data Added to the fragment portion of the object’s URI Must be at the end of the URI fragment portion Is delimited by “?” Example:  file:/c:/dir/library.xmi #//@books.0?Book.ISBN.0131425420? Fragment Query URI Fragment
Saving Fragment Queries If you are using a XMLResource to serialize your objects Override the getURIFragmentQuery(Resource, EObject) method of org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl to return the query that should be serialized for the given EObject Override the  createXMLHelper()  method of  org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl  to return an instance of your XMLHelper The  getURIFragmentQuery(…)  method returns the string that is used as the “query” The string should not contain the delimiter character ( ? ) A null string indicates that there is no query The characters must be valid URI fragment characters (as defined by the specification)
Going Deeper: org.eclipse.emf.ecore.xmi.XMLHelper Interface used by the default resource implementations Not used by clients Single place where the methods used to save and load objects are located Simplifies customizations
Using Fragment Queries EMF doesn’t enforce the use of fragment queries Reasonable approach: Load an object Try to resolve its proxies Identify the remaining (broken) proxies Use the fragment query of the broken proxies to either report the problem to the user or recover the missing objects
Cross-Resource Containment Allows an object hierarchy to be persisted across multiple resources eObject.eResource() may be different from eObject.eContainer().eResource() Must be explicitly enabled The containment reference has to be set to resolve proxies Also, on generated models, the value of the  “Containment Proxies” generator model property has to be set to ‘true’
Enabling Cross-Resource Containment EReference houses = EcoreFactory.eINSTANCE.createEReference(); houses.setName(&quot;houses&quot;); houses.setEType(house); houses.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); houses.setContainment(true); houses. setResolveProxies ( true ); person.getEStructuralFeatures().add(houses); Dynamic Model Generated Model
Cross-Resource Containment { Library library = LibFactory.eINSTANCE.createLibrary(); Book book = LibFactory.eINSTANCE.createBook(); library .getBooks().add(book); System.out.println (library.eResource() + &quot; - &quot; + book.eResource()); Resource  libraryResource  = new ResourceImpl(URI.createURI(&quot; lib &quot;)); libraryResource .getContents().add( library ); System.out.println (library.eResource().getURI() + &quot; - “ +  book.eResource().getURI()); Resource  bookResource  = new ResourceImpl(URI.createURI(&quot; book &quot;)); bookResource .getContents().add( book ); System.out.println (library.eResource().getURI() + &quot; - &quot; +  book.eResource().getURI()); bookResource .getContents().remove( book ); System.out.println (library.eResource().getURI() + &quot; - &quot; +  book.eResource().getURI());  } null - null lib - lib lib - book lib - lib
EcoreUtil Methods for Cross-Resource Containment When the containment tree is spread across multiple files, one may be interested in differentiating the “local” children of an object from children in other resources The  *Proper*  methods available in EcoreUtil only deal with the “local” children of a containment tree All children Local children
Inverse References Sometimes it may be handy to retrieve the opposite of a unidirectional association end For example, the use case you are implementing requires a navigation that was not anticipated when the model was defined EMF provides two mechanisms CrossReferencer ECrossReferenceAdapter
Going Deeper: Associations and References An association between two classes allows their instances to “communicate” with each other Each navigable end of an association is represented by an EReference in Ecore If the association is bidirectional, it will be represented by two references, r1 and r2 where  r1.getEOpposite() == r2 && r2.getEOpposite() == r1 Associations References
Using a CrossReferencer Dynamically computes a map with the target object and the list of settings that “refer” to it This computation may be a long operation depending on the number of objects The map represents a snapshot of the state of the objects As the objects change, the settings’ values may become inconsistent with the map Requires a context to compute the map The context can be a collection of EObjects, a resource, or a resource set, or a combination of these Objects that are not in the scope of the context won’t be available in the map
Using a CrossReferencer { Library  library  = LibFactory.eINSTANCE.createLibrary(); Book  book  = LibFactory.eINSTANCE.createBook(); book.setTitle(&quot;EMF&quot;); Person  dave  = LibFactory.eINSTANCE.createPerson(); library .getBooks().add( book ); library .getWriters().add( dave ); book .getWriters().add( dave ); Map<EObject, Collection<EStructuralFeature.Setting>> map = EcoreUtil.CrossReferencer .find(Collections.singleton( library )); Collection<EStructuralFeature.Setting> settings = map.get(dave); if (settings != null) { for (EStructuralFeature.Setting setting : settings) { if (setting. getEObject () ==  book  &&  setting. getEStructuralFeature () == LibPackage.Literals. BOOK__WRITERS ) { System.out.println (&quot;Found it.  The book is \&quot;&quot; + book.getTitle() + &quot;\&quot;&quot;); } }  } } Found it.  The book is &quot;EMF&quot;
Using the ECrossReferenceAdapter A special adapter that  Attaches itself to all objects in a containment hierarchy May pose a memory footprint problem depending on the number of objects Keeps a CrossReferencer in sync with the state of the objects The application can determine and change the context used when computing the map
Using the ECrossReferenceAdapter { Library  library  = LibFactory.eINSTANCE.createLibrary(); ECrossReferenceAdapter  adapter  = new  ECrossReferenceAdapter (); library.eAdapters().add( adapter ); Book  book  = LibFactory.eINSTANCE.createBook(); book.setTitle(&quot;EMF&quot;); Person  dave  = LibFactory.eINSTANCE.createPerson(); library .getBooks().add( book ); library .getWriters().add( dave ); book .getWriters().add( dave ); Collection<EStructuralFeature.Setting> settings = adapter. getNonNavigableInverseReferences (dave); for (EStructuralFeature.Setting setting : settings) { if (setting. getEObject () ==  book  &&  setting. getEStructuralFeature () == LibPackage.Literals. BOOK__WRITERS ) { System.out.println (&quot;Found it.  The book is \&quot;&quot; + book.getTitle() + &quot;\&quot;&quot;); } }  } Found it.  The book is &quot;EMF&quot;
Resource Tips & Tricks Unloading a resource Resource.unload() EMF’s default implementation performs the following steps: Sets the  loaded  attribute to false; Caches an iterator with all the proper contents of all objects held by the resource Clears the resource’s content, error and warning lists Turns each object returned by the iterator into a proxy and clears its adapter list Fires a notification  Feature ID = Resource. RESOURCE__IS_LOADED You may also remove the resource from the resource set
Resource Tips & Tricks Tracking modification Resource.setTrackingModification(boolean) When activated, EMF’s default implementation performs the following steps: Instantiates an Adapter and registers it on all proper objects The adapter calls Resource.setModified(boolean) after receiving a notification Registers the adapter on any object added to the resource and deregisters it from objects that are removed When deactivated, the default implementation removes the adapter from the objects You can manually define what is the isModified state of a resource
Resource Tips & Tricks Am I loading something? Resource.Internal.isLoading() Every Resource is supposed to implement the Resource.Internal interface When a resource is being loaded the isLoading() method returns true
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Generating Customized Code The EMF code generator can be customized in various ways to meet the needs of your application There are different levels of customization Generator Options Dynamic Templates Generator Extension
Generator Options The EMF code generator provides a number of options which can have a significant effect on the kind of code that is generated from the default templates Suppress Interfaces Suppress EMF Metadata Root Extends Interface Suppress EMF Types Suppress EMF Model Tags
Generator Options All can be adjusted as properties of the GenModel element, the root object in the generator
Suppress Interfaces /** * A representation of the model object * 'Library'. * @model * @generated */ public  interface Library  extends EObject { /** * Returns the value of the ‘Name' attribute. * @model * @generated */ String getName(); ... } /** * A representation of the model object * 'Library'. * @model * @generated */ public  class Library  extends EObjectImpl implements EObject { /** * The default value of the 'Name' attribute. * @model * @generated */ protected static final NAME_EDEFAULT = null; ... }
Suppress Interfaces Improves performance since dispatch through an interface is slower and less likely to be in-lined by a JIT compiler Reduces byte code footprint somewhat Can only be used for models with no multiple inheritance
Suppress EMF Metadata Helps produce an API with no visible EMF dependencies, i.e. a &quot;pure&quot; API /** * The Package for the model. * @model kind=&quot;package&quot; * @generated */ public  interface LibraryPackage  extends EPackage { /** * The package name. * @generated */ String eNAME = &quot;library&quot;; ... /** * The meta object id for the 'Book' class. * @generated */ int BOOK = 0; ... } /** * The Package for the model. * @model kind=&quot;package&quot; * @generated */ public  class LibraryPackageImpl extends EPackageImpl  { /** * The package name. * @generated */ String eNAME = &quot;library&quot;; ... }
Root Extends Interface Helps produce an API with no visible dependencies on EMF, or an API that visibly participates in another framework ‘ Root Extends Class’ and ‘Root Implements Interface’ are also available (classes must implement InternalEObject) /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library { ... } /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library  extends EObject { ... }
Suppress EMF Model Tags Helps produce an API with no visible dependencies on EMF /** * A representation of the model object * 'Library'. * @generated */ public interface Library extends EObject { ... /** * Returns the value of the Writers containment * reference list. * @generated */ EList<Writer> getWriters(); ... } /** * A representation of the model object * 'Library'. *  @model * @generated */ public interface Library extends EObject { ... /** * Returns the value of the Writers containment * reference list. *  @model containment=&quot;true&quot; *  type=&quot;org.eclipse.example.library.Writer&quot; * @generated */ EList<Writer> getWriters(); ... }
Suppress EMF Types EList, EMap, and EObject suppressed Applies to feature, operation and parameter types Helps produce an API with no visible dependencies on EMF /** * Returns the value of the Writers containment * reference list. * @model containment=&quot;true“ *  type=&quot;org.eclipse.exasmple.library.Writer&quot; * @generated */ List <Writer> getWriters(); /** * Returns the value of the Writers containment * reference list. * @model containment=&quot;true&quot; *  type=&quot;org.eclipse.example.library.Writer&quot; * @generated */ EList <Writer> getWriters();
Dynamic Templates The content of the templates used by the EMF code generator can be changed or replaced by enabling dynamic templates Set the value of the ‘Dynamic Templates’ generator model property to ‘true’ Set the value of the ‘Template Directory’ generator model property to the location of the custom templates Dynamic templates can be customized in three ways Replacement Insertions Overrides
Template Replacement Copy default template to the dynamic template directory (with the same name and relative location) and modify as desired Modified template is compiled dynamically and used in place of the default template Must keep in sync with changes in default templates (“clone and own”)…
Template Insertions Can insert content into default templates via insertion points identified using JET @include directive (fail=“silent”) Dynamic template includes default template; insertions are included and compiled dynamically, result is used in place of the default template By convention, insertions are placed in a folder named after the including template and end with a .insert.*jet extension A number of insertion points have been defined for some commonly customized EMF templates (i.e. Class.javajet, ItemProvider.javajet, TestCase.javajet)
Template Overrides Can override content of default templates via override points identified using JET @include directive (fail=“alternative”) Dynamic template includes default template; overrides are included and compiled dynamically, result is used in place of the default template By convention, overrides are placed in a folder named after the including template and end with a .override.*jet extension A number of override points have been defined for some commonly customized EMF templates (i.e. Class.javajet, ResourceFactoryClass.javajet, TestCase.javajet)
Template Insertions and Overrides Simplified example from Class.javajet: <%@  include  file=&quot;Class/genOperation.override.javajetinc&quot;  fail=&quot;alternative&quot;  %> <%@  start  %> public <%=genOperation.getImportedType()%> <%=genOperation.getName()%>(...) { <%if (genOperation.hasBody()) {%> <%=genOperation.getBody(genModel.getIndentation(stringBuffer))%> ... <%} else {%> <%@  include  file=&quot;Class/genOperation.TODO.override.javajetinc&quot;  fail=&quot;alternative&quot;  %> <%@  start  %> // TODO: implement this method throw new UnsupportedOperationException(); <%@  end  %> <%}%> } <%@  include  file=&quot;Class/genOperation.insert.javajetinc&quot;  fail=&quot;silent&quot;  %> <%@  end  %>
Generator Extension EMF’s generator is extensible Code generation is performed by visiting the elements in the model and invoking templates to generate artifacts for each element Control over this process is delegated to GeneratorAdapters via one or more GeneratorAdapterFactory Additional adapter factories can be plugged into the generator to create adapters that generate additional artifacts
Generator Extension Contributing adapters via an extension point: Adapters can be added directly, or via an adapter factory A generic adapter factory is instantiated for each adapter added directly, so it’s more efficient to add multiple adapters via a factory <extension point=&quot; org.eclipse.emf.codegen.ecore.generatorAdapters &quot;> < adapterFactory  class=&quot;com.example.generator.MyGeneratorAdapterFactory&quot;/> < adapter  modelClass=&quot;GenModel&quot; class=&quot;com.example.generator.MyGenModelGeneratorAdapter&quot;/> </extension>
Generator Model Extension It is possible, but not advised, to extend the generator model by subclassing its elements New attributes can be added to support additional code generation options These attributes can be exposed as properties in the generator UI by registering a specialized adapter factory via the org.eclipse.emf.edit.itemProviderAdapterFacotries extension point Protected members of GenModel elements are not considered API: you may have to adapt to changes in the base implementation! A better way to introduce new code generation options is using generator annotations
Going Deeper: GenAnnotations GenAnnotations can be added to any instance of GenBase, i.e. any object in a GenModel containment tree (including GenAnnotations themselves) GenBase provides two methods to work with GenAnnotations getGenAnnotations() getGenAnnotation(String source) A GenAnnotation, like its close relative EAnnotation, defines  A source   attribute, which is typically used to store a URI representing the type of the annotation A details map attribute to store name-value pairs Containment and non-containment references to EObjects
Going Deeper: GenAnnotations The GenAnnotations are usually hidden in the Generator You can unhide them by checking &quot;Show Annotations&quot; in the &quot;Generator&quot; menu
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Performance/Memory Overhead EMF provides a number of mechanisms that can be used to tune the performance and/or memory overhead of your model implementation Code Generator Options Boolean Flags Virtual Feature Delegation Minimal Reflective Methods XMLResource Options
Boolean Flags Generates code that uses (a) consolidated bit field(s) instead of separate fields to represent the values of Boolean attributes and whether unsettable features are set Set the value of the ‘Boolean Flags Field’ generator model property to the name of the bit field(s) to be generated or reused Set the value of the ‘Boolean Flags Reserved Bits’ generator model property to the number of bits in the field(s) that are reserved (e.g. used by parent classes) Helps reduce memory overhead for models with a large number of Boolean attributes or unsettable features
Virtual Feature Delegation Generates code that uses a single, dynamically-allocated array field and associated index field(s) instead of separate fields to represent the values of non-primitive features Set the value of the ‘Feature Delegation’ generator model property to ‘Virtual’ Helps reduce memory overhead for models with a large number of features that are often “sparsely” used
Minimal Reflective Methods Generates reflective methods that delegate to  super , i.e. they delegate switching for any non-matching features to the superclass implementation for dispatching Set the value of the ‘Minimal Reflective Methods’ generator model property to ‘true’ (default) Helps reduce memory (byte code) overhead for models with a large number of inherited features May increase performance overhead for models with deep class hierarchies
XMLResource Options XMLResource offers a set of options that can be used to tweak load and save behavior The options are passed to the resource’s save and load methods as entries in a map The key is the constant that represents the option Each option requires an appropriate value
XMLResource Load Options OPTION_DEFER_IDREF_RESOLUTION Option value: Boolean Defers resolving references within a resource until the whole document has been parsed OPTION_USE_PARSER_POOL Option value: org.eclipse.emf.ecore.xmi.XMLParserPool Provides a parser pool, from which SAXParser instances are created and reused OPTION_USE_XML_NAME_TO_FEATURE_MAP Option value: java.util.Map Enables sharing the cache of mappings between qualified XML names (namespace + local name) and corresponding Ecore features across invocations of load(…), or even among resources
XMLResource Load Options OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List Specifies a list as a place holder for caching information during the subsequent saving of XML documents OPTION_USE_DEPRECATED_METHODS Option value: Boolean Use methods that were deprecated in EMF The default value is Boolean.TRUE
XMLResource Save Options OPTION_FLUSH_THRESHOLD Option value: Integer Specifies a maximum number of characters to allow in the output stream before flushing it OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List Provides a placeholder to cache information about structure of the model (using qualified XML names as a key for caching information) OPTION_CONFIGURATION_CACHE  Option value: Boolean  Enables caching and reusing generic data in repeated save operations, avoiding the cost of reinitializing the data
XMLResource Save Options OPTION_FORMATTED  Option value: Boolean Disables formatting of documents, omitting whitespaces and line brakes, to improve the performance of saving and, subsequently, loading the resulting document OPTION_USE_FILE_BUFFER  Option value: Boolean Enables accumulating output during serialization in a temporary file, rather than an in-memory buffer
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Importers and Exporters Java model Annotated Java Model Importer EMF Model Exporter Java model UML Java model XML Schema Java model Ecore Java model ? Java model ? Java model XML Schema Java model XML Schema for XMI
Model Importers A Model Importer (aka an importer) is responsible for creating an Ecore model from the description of a modeled domain Each importer knows how to handle a specific format of description An importer is also expected to create the generator model (.genmodel file) for the Ecore Model (.ecore file) EMF provides importers that handle the following formats Rational Rose models XML Schemas Annotated Java Interfaces Ecore and EMOF files
Model Exporters A Model Exporter (aka exporter) is able to read an Ecore model and generate another description of the same modeled domain An exporter typically uses the information described in the Generator Model to accomplish its purposes EMF provides two exporters XML Schema XML Schema for XMI EMF also provides an HTML exporter example, which uses JET to produce a package summary
Going Deeper: Why is the Generator Model so important? The generator model acts as a decorator for an Ecore model It provides details that would pollute the model, such as the Qualified name of an EPackage Prefix for package-related class names Actual location of the model, edit, editor, and test source folders When a modeled domain is converted into an EMF model, the importer may be able to capture some generator model details and store them in a .genmodel file The Java package of the annotated Java interfaces Referenced XML Schemas that may or may not be already represented by Ecore models The generator model is useful to an exporter because It can be used to persist details about the exported artifact Some details may be important to properly describe the modeled domain
Using Importers and Exporters The importers and exporters are presented to the user as pages of a standard EMF wizard The registered importers are presented during the execution of the new EMF model or EMF project wizards The list of exporters is shown when the “Export Model…” action is invoked on a .genmodel file The motivation of this design is to let the importers and exporters decide the input that the user needs to provide Each implementation has total control over the number of pages of the wizard and their content The Rose and XML Schema importers are also available as Eclipse applications and Ant tasks
Contributing an Importer via an Extension Point The wizard must be a class that implements EMF’s IModelImporterWizard interface Defines the setters that will be used by the new EMF model and project wizards to communicate the details about the model specification being imported <extension point=&quot; org.eclipse.emf.importer.modelImporterDescriptors &quot;> <modelImporterDescriptor id =&quot;com.mycompany.ModelImporterDescriptor.XYZ&quot;  name=&quot;XYZ class model&quot; extensions=&quot;xyz&quot; wizard =&quot;com.mycompany.ImportWizard&quot;/> </extension>
Contributing an Exporter via an Extension Point The wizard must be a class that implements Eclipse’s IWorkbenchWizard interface The first time the wizard is presented to the user, the method init(IWorkbench, IStructuredSelection) is invoked and the selection argument is either an IFile that contains the generator model or an instance of GenModel <extension point=&quot; org.eclipse.emf.importer.modelExporterDescriptors &quot;> <modelExporterDescriptor id =&quot;com.mycompany.ModelExporterDescriptor.XYZ&quot;  name=&quot;XYZ class model&quot; wizard =&quot;com.mycompany.ExportWizard&quot;/> </extension>
Contributing Importers and Exporters via Global Registries The idea is to add the importer/exporter description to the appropriate list ModelImporterManager.INSTANCE.getModelConverterDescriptors() ModelExporterManager.INSTANCE.getModelConverterDescriptors() The importer and exporter descriptions are quite similar, which led to the creation of a common parent interface
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Backward/Forward Compatibility EMF provides mechanisms that can be used to support migration of data between different versions of a model (or between two different models, for that matter): Use Ecore2Ecore and Ecore2XML to define a mapping between the different model(s) (versions) Use Ecore2XMLExtendedMetaData with save/load options to handle unrecognized data Use a resource handler to pre/post-process data that cannot be mapped automatically Source and target models must have different namespace URIs and XML references must not be based on feature names
Ecore2Ecore Mappings Describe a mapping between two Ecore models Can be created from an Ecore (*.ecore) model via the ‘Map To Ecore…’ context menu item in the Package Explorer or Resource Navigator Typically used as a development-time artifact (only) Can include one-to-one, one-to-many, many-to-one, many-to-many, and one-sided mappings Only one-to-one and one-sided (one-to-none, none-to-one) mappings are useful for data migration
Ecore2XML Mappings Describe a mapping between an Ecore model and its XML representation Can be generated from an Ecore2Ecore (*.ecore2ecore) model via the ‘Generate Ecore to XML Mapping…’ context menu item in the Package Explorer or Resource Navigator Often used as a run-time artifact (in conjunction with Ecore2XMLExtendedMetaData) Can include one-to-one and many-to-one mappings, but only the former are useful for data migration
Ecore2XMLExtendedMetaData Can be used with the OPTION_EXTENDED_META_DATA save/load option defined on XMLResource to affect how data are serialized/deserialized Will consult registered Ecore2XML mappings to determine the XML representation of objects my.y my.x x_2_y.ecore2xml
OPTION_RECORD_UNKNOWN_FEATURE Load option defined on XMLResource Will record data for unrecognized types and features in an extension map (XMLResource#getEObjectToExtensionMap()) on the resource Recorded data will be serialized again when the resource is saved (unless the entries in the map have been cleared) my.x my.y y => x
Resource Handlers Interface XMLResource.ResourceHandler defines callbacks that can be implemented to do special processing before/after a resource is loaded/saved Used with OPTION_RESOURCE_HANDLER save/load option defined on XMLResource Can support backward compatibility by extracting data from a resource’s extension map after it is loaded Can support forward compatibility by inserting data into a resource’s extension map before it is saved
Enabling Data Migration Create a package registry and add entries which map the source namespace URI and target Ecore model location to the target package Create an Ecore2XML registry and add an entry which maps the source namespace URI to the Ecore2XML mapping Create an instance of Ecore2XMLExtendedMetaData based on the package and Ecore2XML registries; pass this extended metadata as the value for the XMLResource.OPTION_EXTENDED_META_DATA load/save option
Enabling Data Migration Pass Boolean.TRUE as the value for the XMLResource.OPTION_RECORD_UNKNOWN_FEATURE load option If required, pass an implementation of XMLResource.ResourceHandler as the value for the XMLResource.OPTION_RESOURCE_HANDLER load/save option
Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
Summary We have seen examples of how flexible and extensible the Eclipse Modeling Framework is Hopefully you have gained greater insight into how some of the more “advanced” features of EMF can be exploited to meet your application’s needs
Part 3: Eclipse Modeling Framework Technologies – Query, Transaction, Validation
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
What is EMFT? A collection of components that “add on” to EMF to provide value-added capabilities for rich applications Currently includes: Validation – a flexible framework for contributing 3 rd -party constraints to model validation Query – an SQL-like Java API for querying EMF resources Transaction – a transaction protocol for concurrent access to EMF resources CDO, Teneo – object-relational mappings for persistence of EMF resources in RDBMSes JET Editor – a rich editor for JET templates
What was EMFT? Formerly in EMFT: OCL – an implementation of the Object Constraint Language for Ecore and UML metamodels; now a component of MDT EODM – an implementation of the Ontology Definition Metamodel for Ecore; now a component of MDT JET (a.k.a. JET2) – next generation of the Java Emitter Templates; now a component of M2T This tutorial will explore the Validation, Query, and Transaction components with a little OCL added for flavour
What does the Validation Framework Provide? Extensibility: Constraint providers contribute constraints from any source they deem fit, including the plugin.xml, constraints embedded in models, or external models Constraint parsers contribute support for constraint specification languages.  Out of the box, the framework implements Java and OCL support. Traversal strategies contribute knowledge of the model structure and how to discover its extent to validate it Constraint categories and bindings help to organize constraints and activate them in specific applications Validation listeners are notified whenever validation occurs, to provide an appropriate response from the application
What does the Validation Framework Provide? Invocation (Triggers) “Batch” validation:  initiated by the user or by the system on some important event, validates all or a selected subset of a model “Live” validation:  initiated automatically by the system to validate a set of changes performed during some transaction.  The semantics of “transaction” are defined by the client Constraints can specify which particular changes trigger them (by feature and event type) Support for OCL constraints EMFT Validation uses the OCL component of the MDT project to provide out-of-box support for specifying constraints using OCL
What does the Query Framework Provide? A convenient Java API for querying an EMF-based model The API is designed to look and feel like SQL, with SELECT and UPDATE statements, FROM clauses, etc. Offers a wide array of reusable and recombinable predicate objects for specifying WHERE clause conditions Supports nested and compound queries Easily customizable for special requirements in traversing models, etc. Support for OCL Provides predicate classes that specify WHERE conditions as OCL constraints (with context or, optionally, context-free)
What does the Transaction API Provide? A transactional editing environment Safe read and write access to EMF resources from multiple concurrent threads Commit protocol providing mechanisms for ensuring model integrity: Validation of the changes performed during the transaction (constraints) using the Validation Framework Pre-commit listeners proactively performing concomitant changes (triggers) to maintain consistency of dependencies Automatic rollback of changes on failure to validate or complete triggers Supports transaction nesting
What does the Transaction API Provide? Read/write transactions Give a thread exclusive access to a ResourceSet for the purpose of modifying its content Ensure that other threads do not observe interim (uncommitted) states of the data (“dirty reads”) Read-only transactions Protect against threads concurrently initializing concrete state of the ResourceSet (such as duplicate resolution of proxies or duplicate initialization of ELists) Can be shared cooperatively by multiple reading threads
What does the Transaction API Provide? Change events Commit of a transaction sends a ResourceSetChangeEvent to interested listeners, with a summary of the changes that the transaction performed Changes are sent as a single batch, and only on successful commit, so that UI refreshes etc. don’t get any “noise” Integration with Eclipse Workbench APIs Support for delegating the EMF CommandStack to an IOperationHistory Leverages the IUndoContext to support separate undo/redo “stacks” where independent changes occur in a single ResourceSet
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
Constraint Providers Constraint providers are of two flavours: static and dynamic Static providers declare their constraints in the plugin.xml of a client plug-in of the constrained model Dynamic providers obtain constraints from an arbitrary source at run-time Both kinds of providers can declare constraint categories and include their constraints in categories defined by any provider Categories are hierarchical namespaces for constraints Constraints are grouped by category in the preference page
Static Constraint Provider <extension point=&quot; org.eclipse.emf.validation.constraintProviders &quot;> < category name =&quot;Library Constraints&quot;   id =&quot;com.example.library&quot;> <constraintProvider> < package namespaceUri =&quot;http:///www.eclipse.org/Library/1.0.0&quot;/> <constraints   categories =&quot;com.example.library&quot;> <constraint lang =&quot;Java&quot; class =&quot;com.example.constraints.UniqueLibraryName&quot; severity =&quot;WARNING&quot; mode =&quot;Batch&quot; name=&quot;Library Must have a Unique Name&quot; id=&quot;com.example.library.LibraryNameIsUnique&quot; statusCode=&quot;1&quot;> <description>Libraries have unique names.</description> <message>{0} has the same name as another library.</message> < target class =&quot;Library&quot;/> </constraint> </constraints> </constraintProvider> </extension>
Dynamic Constraint Provider Registered by name of a class implementing the  IModelConstraintProvider  interface Indicate the packages for which they supply constraints Biggest difference is the absence of a  <constraints>  element System can optionally cache the provided constraints <extension point=&quot; org.eclipse.emf.validation.constraintProviders &quot;> < category name =&quot;Library Constraints&quot;   id =&quot;com.example.library&quot;> <constraintProvider   class =&quot;com.example.MyConstraintProvider&quot;   cache =&quot;false&quot;> < package namespaceUri =&quot;http:///www.eclipse.org/Library/1.0.0&quot;/> </constraintProvider> </extension>
Dynamic Constraint Provider A dynamic constraint provider implements the  IModelConstraintProvider  interface A descriptor supplies meta-data about a constraint The validation algorithm is supplied by the constraint object in the  validate()  method
Constraints Descriptor provides: ID and localizable name Evaluation mode Target EClasses Triggering events (live) Severity, error message Categorization Enabled state Much of this information appears in the preference page Users can choose which constraints to activate
Evaluation Modes Batch validation is usually explicitly requested by the user, via a menu action or toolbar button Live validation is performed automatically as changes are made to EMF resources Live constraints indicate which specific changes trigger them <constraint mode =&quot;Live&quot; …  > <description>Libraries have unique names.</description> <message>{0} has the same name as: {1}.</message> <target class=&quot;Library&quot;> < event name =&quot;Set&quot;>   < feature name =&quot;name&quot;/>   </ event > </target> </constraint>
Validation Service Evaluation of constraints is performed via the Validation Service The service provides validators corresponding to the available evaluation modes By default, batch validation includes live constraints, also, for completeness
Validation Service To validate one or more elements, in batch mode, simply create a new validator and ask it to validate: List objects = myResource.getContents();   // objects to validate // create a validator IValidator   validator  = ModelValidationService.getInstance()   . newValidator (EvaluationMode. BATCH ); // use it! IStatus  results  = validator. validate (objects); if (!results.isOK()) { ErrorDialog.openError(null, &quot;Validation&quot;, &quot;Validation Failed&quot;,   results); }
Validation Service Live validation does not validate objects, but rather  Notification s indicating changes to objects List< Notification > notifications = … ;   // some changes that we observed // create a validator IValidator validator = ModelValidationService.getInstance()   .newValidator(EvaluationMode. LIVE ); // use it! IStatus results = validator.validate( notifications ); if (!results.isOK()) { ErrorDialog.openError(null, &quot;Validation&quot;, &quot;Validation Failed&quot;,   results); }
Creating Constraints Specifying a constraint doesn’t necessarily require any code Requires the OCL component of the MDT project <constraint lang=&quot; OCL &quot; mode=&quot;Batch&quot; …  > <description>Libraries have unique names.</description> <message>{0} has the same name as: {1}.</message> <target class=&quot;Library&quot;/> <![CDATA[ Library.allInstances()->forAll(l |   l <> self implies l.name <> self.name) ]]> </constraint>
Creating Constraints Sometimes the easiest or best way to formulate a constraint is in Java Java constraints extend the AbstractModelConstraint class The validation context provides the  validate() method with information about the validation operation
Validation Context Provides the element being validated (the target) Indicates the current evaluation mode (live or batch) In case of live invocation, provides the changed feature and the event type Allows constraints to cache arbitrary data for the duration of the current validation operation Provides convenient methods for reporting results Provides the ID of the constraint that is being invoked
Creating Constraints public class LibraryNameIsUnique extends  AbstractConstraint  { public IStatus  validate (IValidationContext ctx) { Library target = (Library) ctx. getTarget ();  // object to validate // does this library have a unique name? Set<Library> libs = findLibrariesWithName(target.getName()); if (libs.size() > 1) { // report this problem against all like-named libraries   ctx. addResults (libs);   // don’t need to validate these other libraries libs.remove(target); ctx. skipCurrentConstraintFor (libs);   return ctx.createFailureStatus(new Object[] {   target, libs}); } return ctx. createSuccessStatus (); }  }
Listening for Validation Events Every validation operation executed by the Validation Service generates an event The event indicates the kind of validation performed, on what objects, and what were the results (incl. severity) Listeners registered on the extension point are lazily initialized when their selection criteria are met <extension point=&quot; org.eclipse.emf.validation.validationListeners &quot;> < listener class =&quot;com.example.validation.ProblemsReporter&quot;> < clientContext id =&quot;com.example.MyClientContext&quot;/> </listener> </extension>
Reporting Problems Problems are reported as IConstraintStatus objects.  A status knows: The constraint that was violated The objects that violated it The severity and error message, as usual for an IStatus The marker utility encodes all of this information in a problem marker on the appropriate resource, to show in the Problems view
Reporting Problems public class ProblemsReporter implements  IValidationListener  { public void   validationOccurred (ValidationEvent event) { if (event. matches (IStatus.WARNING | IStatus.ERROR)) { // fabricate a multi-status for the MarkerUtil to consume List results = event. getValidationResults ();  IConstraintStatus multi = new MultiStatus( &quot;com.example.MyPlugin&quot;, 1, (IStatus[])results.toArray(new IStatus[results.size()]), &quot;Problems were found by validation&quot;, null); try { // create problem markers on the appropriate resources MarkerUtil.createMarkers (multi);   } catch ( CoreException e ) { // creation of problem markers failed for some reason MyPlugin.getLog().log(e.getStatus()); } } }  }
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
Query Statements SELECT  statements filter the objects provided by a  FROM clause according to the conditions specified in the WHERE  clause SELECT s are  IEObjectSource s, so they can be used in  FROM clauses to nest queries UPDATE  statements use a SET  clause to update the objects provided by the  FROM  clause (filtered, of course, by the  WHERE  clause)
The FROM Clause Uses EMF’s tree iterators to walk the objects being queried Optionally specifies an  EObjectCondition filter Search scope is encapsulated in an IEObjectSource provides objects via an iterator.  The  FROM  descends into the contents of these objects if it is a hierarchical  IteratorKind
The WHERE Clause The  WHERE  clause specifies a single filter condition This filter condition can be arbitrarily complex Filters can be combined in innumerable ways using the common boolean operators The  IN  filter detects whether an object is an element of a supplied set (as in SQL)
The WHERE Clause The framework provides a condition on the model type of objects Can also filter for objects that are identical to some target ( EObjectInstanceCondition )
The WHERE Clause The framework provides conditions that filter objects based on values of their features In particular, the EObjectReferencerCondition filters for cross-references to a particular object
The WHERE Clause: Condition Policies For multi-valued structural features, the ConditionPolicy determines whether a Condition must match all values or just any value Correspond to the relational    (for-all) and    (exists) quantifiers
The WHERE Clause: Prune Handlers Just as with EMF’s tree iterators, a query’s iteration over its scope can be  pruned Any  EObjectCondition  can have a PruneHandler  that determines whether the search tree can be pruned This allows the query to skip over entire sub-trees when a condition knows that it will never be satisfied for any of the contents of the current object The default prune handler in most cases is  NEVER  which, as the name implies, never prunes
The WHERE Clause: Other Conditions The framework includes a variety of conditions for working with primitive-valued  EAttribute s Including strings, booleans, and numbers of all kinds Adapters convert inputs to the required data type Default implementations simply cast, assuming that the values already conform Can be customized to convert values by whatever means is appropriate
OCL Conditions OCL can be used to specify  WHERE clause conditions Only available when the OCL component of MDT is installed An  OCLConstraintCondition  specifies a boolean-valued expression (i.e., a constraint) that selects those elements for which the expression is  true OCL expressions can be contextful or context-free
The UPDATE Statement The  UPDATE  statement behaves much like a  SELECT , except that it passes its result objects through the client-supplied  SET  clause The result of the  UPDATE  is the subset of the selected objects for which the  SET  clause returned true (indicating that they were, in fact, modified)
SELECT Query in Action Queries can be used for anything from simple search functions to complex structural analysis They can even be used to implement validation constraints! IQueryResult  result = new  SELECT ( new  FROM (res.getContents()), new  WHERE (new  EObjectAttributeValueCondition ( EXTLibraryPackage.Literals.WRITER__NAME, new  StringRegularExpressionValue (&quot;.*Da.*&quot;)))).execute(); for (EObject next :  result .getEObjects()) { Writer writer = (Writer) next; System.out.println (“Found “ + writer.getName()); } Found Dave Steinberg Found Christian Damus
SELECT Query with OCL Condition Context-free OCL conditions are applied to any element on which they can be parsed IQueryResult result = new SELECT( new FROM(res.getContents()), new WHERE(new  OCLConstraintCondition ( &quot; self.books->isEmpty() &quot;, null  /* no EClass implies context-free */))).execute(); for (EObject next : result.getEObjects()) { String label = ((IItemLabelProvider) adapterFactory.adapt( next, IItemLabelProvider.class)).getText(next); System.out.println (&quot;Found &quot; + label); } Found Library New Library Found Writer Unpublished Author
UPDATE Query in Action IQueryResult result = new  UPDATE ( new FROM(res.getContents()), new WHERE(new OCLConstraintCondition( &quot;Employee->forAll(e | e.manager <> self)&quot;, EXTLibrary.Literals.EMPLOYEE)), new   SET () { public boolean   set(EObject eObject) { Employee emp = (Employee) eObject; emp. setSalary (emp.getSalary() * 1.05)); return true ; // updated this one }}).execute(); for (EObject next :  result .getEObjects()) { Employee emp = (Employee) next; System.out.println (“Updated “ + emp.getFirstName() + &quot; &quot; + emp.getLastName()); } Updated Ed Merks Updated Dave Steinberg Updated Kenn Hussey Updated Christian Damus
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
What is a Transaction? A transaction is a discrete unit of work in a resource set This work may be reading and writing the resource set contents or simply reading Transactions provide model integrity guarantees Isolation of concurrent threads to prevent data corruption Validation of changes on commit, rolling back (undoing those changes) automatically when data integrity is violated Automatic execution of triggers on commit, to proactively maintain data integrity This is not a concurrent transactional environment Transactions on multiple threads execute in strictly serial order
What is a Transaction? Transactions in a resource set are managed by a TransactionalEditingDomain Read/write transactions are created by execution of commands on the domain’s TransactionalCommandStack Read-only transactions are created by execution of Runnable s via  TransactionalEditingDomain::runExclusive() Most clients will never need to interact directly with  Transaction  objects, but only with the editing domain
Creating Transactional Editing Domains Transactional editing domains are created by factories Use the  TransactionalEditingDomain.Factory.INSTANCE  shared instance to create a private domain for your editor To share one domain instance amongst multiple editors in an application, register a domain ID Add your editing domain instance to the  TransactionalEditingDomain.Registry.INSTANCE Or, register it statically on the editingDomains extension point, specifying a factory for the registry to create it on demand <extension point=&quot; org.eclipse.emf.transaction.editingDomains &quot;> < domain id =&quot;com.example.MyEditingDomain&quot; factory =&quot;com.example.domain.MyCustomFactory&quot;/> <!– factory is optional; implied default is the shared instance --> </extension>
Obtaining the Editing Domain Any editor that needs to access the registered editing domain simply gets it from the registry It is lazily created, using the associated factory, on first access static final String DOMAIN_ID = “ com.example.MyEditingDomain ”; public void init(IEditorSite site, IEditorInput input) throws PartInitException { // get our editing domain domain = TransactionalEditingDomain. Registry.INSTANCE .getEditingDomain(DOMAIN_ID); // load our input resource String fileName = ((IFileEditorInput) input).getFile() .getLocation(); resource = domain. loadResource (fileName); }
Creating Read/Write Transactions To do work in a read/write transaction, simply execute a  Command  on the  TransactionalCommandStack Just like using a regular EMF Editing Domain If the transaction needs to roll back, it will be undone automatically and will not be appended to the stack In order to find out when rollback occurs, use the  TransactionalCommandStack::execute(Command, Map)  method, which  throws RollbackException , instead of using  CommandStack::execute(Command) This method also accepts a map of options to configure the transaction that will be created (more on options, later)
RecordingCommands The RecordingCommand class is a convenient command implementation for read/write transactions Uses the change information recorded (for possible rollback) by the transaction to “automagically” provide undo/redo TransactionalCommandStack stack; stack. execute (new  RecordingCommand () { protected void  doExecute () { Iterator iter = resource.getAllContents(); while (iter.hasNext()) {   // changes are determined on-the-fly Object next = iter.next(); if (next instanceof Library) { ((Library) next).getBooks().add(   LibraryFactory.eINSTANCE.createBook()); } } }}, Collections.EMPTY_MAP);
Transaction Options The  TransactionalCommandStack::execute()  method accepts a map of options defined by the  Transaction  interface that determine how changes occurring during the transaction are handled: OPTION_NO_NOTIFICATIONS : changes are not included in post-commit change events OPTION_NO_TRIGGERS : changes are not included in pre-commit change events OPTION_NO_VALIDATION : changes are not validated OPTION_NO_UNDO :  changes are not recorded for undo/redo and rollback.  Use with extreme caution!
Transaction Options (continued from previous slide) OPTION_UNPROTECTED : implies  OPTION_NO_UNDO ,   OPTION_NO_VALIDATION , and  OPTION_NO_TRIGGERS .  In addition, permits writing to the resource set even in an otherwise read-only context.  Use with even more extreme caution! The  CommandStack::undo()  and  ::redo()  methods use the following options for the undo/redo transaction: OPTION_NO_UNDO :  because we are undoing or redoing a previous recording, there is no need to record anew OPTION_NO_TRIGGERS :  triggers performed during execution were recorded and are automatically undone; any additional changes would be inappropriate OPTION_NO_VALIDATION :  there is no need to validate a reversion to a previous state of the data
Transaction Options The pre-defined options only apply to read/write transactions Permitted on read-only transactions but have no effect Extensions of the transaction API can define custom options TransactionalCommandStack stack; Library library; // don’t tell the UI that we are changing the library name stack. execute ( SetCommand.create(domain, library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;Secret Name&quot;), Collections.singletonMap(   Transaction. OPTION_NO_NOTIFICATIONS , Boolean.TRUE));
Creating Read-Only Transactions To read the contents of the resource set safely, use the  runExclusive()  API: TransactionalEditingDomain domain; domain. runExclusive (new  Runnable () { public void  run () { Iterator iter = resource.getAllContents(); while (iter.hasNext()) { Object next = iter.next(); if (next instanceof Library) { Library lib = (Library) next; System.out.println (lib.getName() + &quot; inventory: &quot; + lib.getBooks().size() + &quot; books&quot;); } } }}, Collections.EMPTY_MAP); Main Branch inventory: 3033 books West Branch inventory: 2570 books South Branch inventory: 1318 books
Transaction Sharing Read-only transactions on multiple threads can be interleaved by cooperatively yielding their read lock Recommended for long-running read operations Call  TransactionalEditingDomain::yield()  to yield read access to other threads waiting for read-only transactions Yielding thread waits until other threads return read access to it either by finishing their transactions or by yielding Yielding is fair:  read access is always passed to the thread that has waited longest Write access is not shared in this way Readers cannot yield to writers Writers cannot yield to any others
Transaction Sharing final TransactionalEditingDomain domain; final IProgressMonitor monitor; // acquire read transaction on this thread domain. runExclusive (new  Runnable () { public void run() { while (moreToRead()) { // … do a bunch of reading … readSomeStuff(); // checking the progress monitor is a good opportunity to //  yield to other readers if (monitor.isCancelled()) { forgetIt(); break; } domain. yield ();  // just returns if no readers waiting   } }});
Transaction Sharing A thread that owns a transaction can lend it to another thread using a  PrivilegedRunnable The privileged runnable takes over the transaction for the duration of its  run()  method Can be used to share read-only  and  read-write transactions Ideal for runnables that need to access the resource set and the UI thread at the same time: Pass the privileged runnable to  Display.syncExec(Runnable)  API to run on the UI thread Must only be used with synchronous inter-thread communication such as  syncExec The originator thread loses the transaction during the runnable
Transaction Sharing TransactionalEditingDomain domain; final org.eclipse.swt.widgets.List bookList; // acquire read transaction on this thread domain. runExclusive (new  Runnable () { public void run() { // hand it off to the UI thread to read the library and update //  the list widget Display.syncExec (domain. createPrivilegedRunnable ( new Runnable() { public void   run () { // the UI thread now has the transaction List<String> bookTitles = new ArrayList<String>();  for (Book book : library.getBooks) { bookTitles.add(book.getTitle()); } }   // the UI thread gives up the transaction }));
Change Listeners EMF provides an  Adapter  mechanism to notify listeners when objects change In a transactional environment, though, we can end up reacting to changes only to find that they are reverted when a transaction rolls back Enter the  ResourceSetListener Post-commit event notifies a listener of all of the changes, in a single batch, that were committed by a transaction If a transaction rolls back, no event is sent because there were no changes There are exceptions for changes that are not (and need not be) undone, such as resource loading and proxy resolution
Change Listeners ResourceSetChangeEvent provides the changes that occurred Transaction  additionally has a  ChangeDescription summarizing the changes Listeners can declare filters to receive only events of interest to them ResourceSetListenerImpl  is a convenient base class providing no-ops for the listener call-backs
Change Listeners Resource set listeners are added to the transactional editing domain Listeners can be registered statically against an editing domain ID Ensures that the listener is attached as soon as the domain comes into being Resolves the problem of timing the addition of listeners domain. addResourceSetListener (new  MyListener ()); <extension point=&quot; org.eclipse.emf.transaction.listeners &quot;> < listener class =&quot;com.example.MyListener&quot;> < editingDomain id =&quot;com.example.MyEditingDomain&quot;/> </listener> </extension>
Post-Commit Listeners A post-commit listener just overrides  ResourceSetListenerImpl.resourceSetChanged() DemultiplexingListener  implements this by dispatching the notifications one by one to the  handleNotification()  method class MyListener extends  ResourceSetListenerImpl   {   public void   resourceSetChanged (ResourceSetChangeEvent event) {   System.out.println(&quot;Domain &quot; +  event .getEditingDomain().getID() + &quot; changed &quot; +  event .getNotifications().size() + &quot; times&quot;); } } class MyDemuxedListener extends  DemultiplexingListener  { protected void  handleNotification (TransactionalEditingDomain domain,   Notification notification) { System.out.println(&quot;Domain &quot; +  domain .getID() + &quot; changed: &quot; +  notification .getNotifier()); } }
Post-Commit Listeners Advantages of the  ResourceSetChangedEvent  include: Listeners know that the changes are permanent Notifications can be processed efficiently as an aggregate Don’t need to worry about dependency on “future” changes No further changes can occur while the change event is being dispatched Listeners are invoked in read-only transactions, so that they can safely read the resource set while analyzing the changes Listeners need to be aware that notifications are delayed relative to the timing of the changes Notifications are only received after all changes are complete Any given notification may not correspond to the current state of the resource set, depending on subsequent changes
Pre-Commit Listeners Before a transaction closes, pre-commit listeners are notified of the changes performed Listeners can provide additional changes, in the form of commands, to be appended to the transaction As with post-commit listeners, the pre-commit listener is invoked in a read-only transaction, so it does not make changes “directly” These commands implement proactive model integrity, as do triggers in RDBMS.  Hence the term “trigger command” Trigger commands are executed in a nested transaction This procedure is recursive:  the nested transaction also invokes pre-commit listeners when it commits
Pre-Commit Listeners class MyListener extends  ResourceSetListenerImpl  { MyListener() {  // only interested in changes to Library objects super(NotificationFilter. createNotifierTypeFilter (   EXTLibraryPackage.Literals.LIBRARY)); }   public Command  transactionAboutToCommit (ResourceSetChangeEvent event) { List  commands  = new ArrayList(); Iterator iter = event.getNotifications().iterator(); while (iter.hasNext()) { Notification next = (Notification) iter.next(); Library library = (Library) next.getNotifier(); if (library.getName() == null) commands.add( SetCommand.create ( event.getEditingDomain(), library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;A library&quot;)); } return  commands.isEmpty()? null :  new   CompoundCommand(commands) ; } }
Pre-Commit Listeners The  TriggerListener  class is convenient  for processing notifications one by one, where appropriate class MyTriggerListener extends  TriggerListener  { MyListener() {  // only interested in changes to Library objects super(NotificationFilter.createNotifierTypeFilter(   EXTLibraryPackage.Literals.LIBRARY)); }   protected Command  trigger (TransactionalEditingDomain  domain , Notification  notification ) { Library library = (Library) next.getNotifier(); if (library.getName() == null) { return  SetCommand.create(domain, library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;A library&quot;); } return null; } }
Transaction Validation When a read/write transaction commits, all of the changes that it performed are checked using the Validation Framework’s live validation capability If problems of error severity or worse are detected, then the transaction rolls back Pre-commit listeners can also force the transaction to roll back by throwing a  RollbackException If a pre-commit listener cannot construct the command that it requires to maintain integrity, then it should roll back
Transaction Nesting Both read-only and read-write transactions can nest to any depth Post-commit events are sent only when the root transaction commits Because even after a nested transaction has committed, it can be rolled back if its parent (or some ancestor) rolls back Pre-commit events are sent at every level of nesting Because a parent transaction may assume data integrity conditions guaranteed by triggers when it resumes Validation is performed on all changes when a root transaction commits Because triggers must be invoked first, in nested transactions
Transaction Nesting Nested transactions inherit options from their parents The standard options cannot be disinherited.  e.g., if a parent transaction does not send post-commit notifications, then none of its descendents will, either, even if they explicitly specify  Boolean.FALSE  for that option Nested transactions can, however, apply more options than their parents e.g., a child transaction can disable notifications.  When its parent commits, the changes that it reports will simply exclude any that occurred during the execution of the child The inheritance of custom options in an extension of the transaction API is defined by that extension
Transaction Lifecycle Overview
UI Utilities The Transaction API includes some utilities for building transactional editors Use the editing domain to create read-only and/or read-write transactions as necessary Substitute for the default EMF.Edit implementations
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
Workbench Integration The  WorkspaceEditingDomainFactory  creates editing domains whose command stacks delegate undo/redo history to the Eclipse Workbench’s  IOperationHistory
Workbench Integration To use the operation-history-enabled editing domain with your editor, simply register it with the appropriate factory class The  IWorkspaceCommandStack  delegates to an operation history Using  IUndoContext s, editors for different resources in the same editing domain can provide undo/redo menus that show only the changes affecting that editor <extension point=&quot; org.eclipse.emf.transaction.editingDomains &quot;> <editingDomain id=&quot;com.example.MyEditingDomain&quot; factory=&quot; org.eclipse.emf.workspace.WorkspaceEditingDomainFactory &quot;/> </extension>
EMF Operations The command stack internally wraps EMF Command s in undoable operations and executes them on the operation history Clients can also construct  Abstract- EMFOperation s and execute them on the history CompositeEMFOperation s can freely compose both EMF and non-EMF changes
EMF Operations AbstractEMFOperation s execute themselves within a transaction on their editing domain Provides rollback support and automatic undo/redo just as the  RecordingCommand  does CompositeEMFOperation s can compose EMF operations and operations on other domains e.g., a composite can change objects in an EMF resource as well as edit parts in a GEF drawing surface and code in Java source files that are all interrelated Undo/redo is fully supported and preserves ordering dependencies between EMF and non-EMF changes Transaction rollback correctly undoes non-EMF changes
EMF Operations IOperationHistory history = workbench.getOperationSupport() .getOperationHistory(); IUndoableOperation operation = new  AbstractEMFOperation (domain, “ Create Books in Libraries”) { protected IStatus  doExecute (IProgressMonitor monitor, Iadaptable info) throws ExecutionException { Iterator iter = resource.getAllContents(); while (iter.hasNext()) {  // changes are determined on-the-fly Object next = iter.next(); if (next instanceof Library) { ((Library) next).getBooks().add(   LibraryFactory.eINSTANCE.createBook()); } } return  Status.OK_STATUS; }}; operation. addUndoContext (myEditorContext); history. execute (operation, new NullProgressMonitor(), null);
Transaction Options As is the case with  Command s, EMF operations can execute with transaction options A  Map  of options can be passed to the operation constructor.  These are used during execution to initialize the transaction The  AbstractEMFOperation::undo()  and  ::redo()  methods use the following transaction options: OPTION_NO_UNDO :  because we are undoing or redoing a previous recording, there is no need to record anew OPTION_NO_TRIGGERS : triggers performed during execution were recorded and are automatically undone; any additional changes would be inappropriate OPTION_NO_VALIDATION :  there is no need to validate a reversion to a previous state of the data
Resource Undo Context The editing domain for workbench integration automatically applies contexts to operations that are executed on its history For each resource affected by a transaction, a resource undo context is applied to the operation A resource is affected by any change to an object that it contains or by a change in another resource that adds a cross-reference to it  An editor that uses a resource context as its editor context will populate its undo and redo menus with operations that affected its resource
Undo/Redo Actions The workbench integration API provides replacements for EMF’s undo/redo actions that delegate to the operation history API’s action handlers These wrappers create undo/redo action handlers on the undo context obtained by adapting the active editor part to the  IUndoContext type Usually this undo context is a  ResourceUndoContext
Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
Summary We have learned how to validate EMF resources on demand and on-the-fly using the EMFT Validation Framework search EMF resources using the EMFT Query Framework implement data integrity in EMF resources in a concurrent programming environment using the EMFT Transaction API integrate EMF-based editors with the Eclipse Workbench’s undo/redo framework using the EMFT Transaction API
Resources EMF documentation in Eclipse help Overviews, tutorials, API reference EMF project Web site http://www.eclipse.org/modeling/emf/ Overviews, tutorials, newsgroup, Bugzilla Eclipse Modeling Framework  by Frank Budinsky et al. Addison-Wesley; 1st edition  (August 13, 2003) ISBN: 0131425420.
Resources EMFT documentation in the Eclipse on-line help Overviews, tutorials, and API reference (Javadocs) EMFT components Web site Home page:  http://www.eclipse.org/emft Newsgroup:  news://news.eclipse.org/eclipse.technology.emft Bugzilla:  https://bugs.eclipse.org/bugs/ Wiki:  http://wiki.eclipse.org/EMFT
Legal Notices IBM, Rational, WebSphere, Lotus, alphaWorks, and Rational Rose are registered trademarks of International Business Machines Corp. in the United States, other countries, or both. Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.  Other company, product, or service names may be trademarks or service marks of others.
Ad

More Related Content

What's hot (20)

Análise e Projeto de Sistemas com UML e Java
Análise e Projeto de Sistemas com UML e JavaAnálise e Projeto de Sistemas com UML e Java
Análise e Projeto de Sistemas com UML e Java
armeniocardoso
 
Padroes De Projeto
Padroes De ProjetoPadroes De Projeto
Padroes De Projeto
ejdn1
 
Aula 1 - Revisão UML
Aula 1 - Revisão UMLAula 1 - Revisão UML
Aula 1 - Revisão UML
Rosanete Grassiani dos Santos
 
Ferramentas para testes de software
Ferramentas para testes de softwareFerramentas para testes de software
Ferramentas para testes de software
Norton Guimarães
 
UML
UMLUML
UML
Roberto Grande
 
GMF : Create your graphical DSL - EclipseCon 11
GMF : Create your graphical DSL - EclipseCon 11GMF : Create your graphical DSL - EclipseCon 11
GMF : Create your graphical DSL - EclipseCon 11
Chauvin Mariot
 
Requisitos Ágeis
Requisitos ÁgeisRequisitos Ágeis
Requisitos Ágeis
André Faria Gomes
 
Driving your BA Career - From Business Analyst to Business Architect
Driving your BA Career - From Business Analyst to Business ArchitectDriving your BA Career - From Business Analyst to Business Architect
Driving your BA Career - From Business Analyst to Business Architect
Enterprise Architects
 
Testes automatizados end-to-end com WordPress por Fabio Nas
Testes automatizados end-to-end com WordPress por Fabio NasTestes automatizados end-to-end com WordPress por Fabio Nas
Testes automatizados end-to-end com WordPress por Fabio Nas
WordCamp Floripa
 
Integração Contínua
Integração ContínuaIntegração Contínua
Integração Contínua
Jackson Veroneze
 
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
Erol Bozkurt
 
Analise de Requisitos
Analise de RequisitosAnalise de Requisitos
Analise de Requisitos
elliando dias
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de Software
Capgemini
 
Introdução a Testes de Software - Unidade I
Introdução a Testes de Software - Unidade IIntrodução a Testes de Software - Unidade I
Introdução a Testes de Software - Unidade I
João Lourenço
 
Enterprise Architecture & IT standards
Enterprise Architecture &  IT standardsEnterprise Architecture &  IT standards
Enterprise Architecture & IT standards
Louw Labuschagne
 
Engenharia de requisitos
Engenharia de requisitosEngenharia de requisitos
Engenharia de requisitos
Mailson Queiroz
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1
Shahzad
 
Data driven Automation Framework with Selenium
Data driven Automation Framework with Selenium Data driven Automation Framework with Selenium
Data driven Automation Framework with Selenium
Edureka!
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service Testing
Ganesh Mandala
 
Apresentação da UML
Apresentação da UMLApresentação da UML
Apresentação da UML
Eliseu Castelo
 
Análise e Projeto de Sistemas com UML e Java
Análise e Projeto de Sistemas com UML e JavaAnálise e Projeto de Sistemas com UML e Java
Análise e Projeto de Sistemas com UML e Java
armeniocardoso
 
Padroes De Projeto
Padroes De ProjetoPadroes De Projeto
Padroes De Projeto
ejdn1
 
Ferramentas para testes de software
Ferramentas para testes de softwareFerramentas para testes de software
Ferramentas para testes de software
Norton Guimarães
 
GMF : Create your graphical DSL - EclipseCon 11
GMF : Create your graphical DSL - EclipseCon 11GMF : Create your graphical DSL - EclipseCon 11
GMF : Create your graphical DSL - EclipseCon 11
Chauvin Mariot
 
Driving your BA Career - From Business Analyst to Business Architect
Driving your BA Career - From Business Analyst to Business ArchitectDriving your BA Career - From Business Analyst to Business Architect
Driving your BA Career - From Business Analyst to Business Architect
Enterprise Architects
 
Testes automatizados end-to-end com WordPress por Fabio Nas
Testes automatizados end-to-end com WordPress por Fabio NasTestes automatizados end-to-end com WordPress por Fabio Nas
Testes automatizados end-to-end com WordPress por Fabio Nas
WordCamp Floripa
 
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
007 Uml Modelleri Analiz Ve Tasarim [74 Slides]
Erol Bozkurt
 
Analise de Requisitos
Analise de RequisitosAnalise de Requisitos
Analise de Requisitos
elliando dias
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de Software
Capgemini
 
Introdução a Testes de Software - Unidade I
Introdução a Testes de Software - Unidade IIntrodução a Testes de Software - Unidade I
Introdução a Testes de Software - Unidade I
João Lourenço
 
Enterprise Architecture & IT standards
Enterprise Architecture &  IT standardsEnterprise Architecture &  IT standards
Enterprise Architecture & IT standards
Louw Labuschagne
 
Engenharia de requisitos
Engenharia de requisitosEngenharia de requisitos
Engenharia de requisitos
Mailson Queiroz
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1
Shahzad
 
Data driven Automation Framework with Selenium
Data driven Automation Framework with Selenium Data driven Automation Framework with Selenium
Data driven Automation Framework with Selenium
Edureka!
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service Testing
Ganesh Mandala
 

Viewers also liked (9)

Epf composer overviewpart2
Epf composer overviewpart2Epf composer overviewpart2
Epf composer overviewpart2
Abdelkader Larbi
 
3 g ngp228
3 g ngp2283 g ngp228
3 g ngp228
ramu kumar
 
EclipseCon 2006: Introduction to the Eclipse Modeling Framework
EclipseCon 2006: Introduction to the Eclipse Modeling FrameworkEclipseCon 2006: Introduction to the Eclipse Modeling Framework
EclipseCon 2006: Introduction to the Eclipse Modeling Framework
Dave Steinberg
 
Eclipse Modeling Framework
Eclipse Modeling FrameworkEclipse Modeling Framework
Eclipse Modeling Framework
Ajay K
 
What every Eclipse developer should know about EMF
What every Eclipse developer should know about EMFWhat every Eclipse developer should know about EMF
What every Eclipse developer should know about EMF
Philip Langer
 
BTS SITE VISIT
BTS SITE VISITBTS SITE VISIT
BTS SITE VISIT
bhargav_shankhalpara
 
Presentation Rf Optimization And Planning
Presentation  Rf Optimization And PlanningPresentation  Rf Optimization And Planning
Presentation Rf Optimization And Planning
Ummaarraa Raa
 
Construction of telecommunication towers
Construction of telecommunication towersConstruction of telecommunication towers
Construction of telecommunication towers
snookala
 
Bts installation & commisioning.ppt
Bts installation & commisioning.pptBts installation & commisioning.ppt
Bts installation & commisioning.ppt
AIRTEL
 
Epf composer overviewpart2
Epf composer overviewpart2Epf composer overviewpart2
Epf composer overviewpart2
Abdelkader Larbi
 
EclipseCon 2006: Introduction to the Eclipse Modeling Framework
EclipseCon 2006: Introduction to the Eclipse Modeling FrameworkEclipseCon 2006: Introduction to the Eclipse Modeling Framework
EclipseCon 2006: Introduction to the Eclipse Modeling Framework
Dave Steinberg
 
Eclipse Modeling Framework
Eclipse Modeling FrameworkEclipse Modeling Framework
Eclipse Modeling Framework
Ajay K
 
What every Eclipse developer should know about EMF
What every Eclipse developer should know about EMFWhat every Eclipse developer should know about EMF
What every Eclipse developer should know about EMF
Philip Langer
 
Presentation Rf Optimization And Planning
Presentation  Rf Optimization And PlanningPresentation  Rf Optimization And Planning
Presentation Rf Optimization And Planning
Ummaarraa Raa
 
Construction of telecommunication towers
Construction of telecommunication towersConstruction of telecommunication towers
Construction of telecommunication towers
snookala
 
Bts installation & commisioning.ppt
Bts installation & commisioning.pptBts installation & commisioning.ppt
Bts installation & commisioning.ppt
AIRTEL
 
Ad

Similar to EclipseCon 2007: Effective Use of the Eclipse Modeling Framework (20)

Eclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Eclipse World 2007: Fundamentals of the Eclipse Modeling FrameworkEclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Eclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Dave Steinberg
 
EclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
EclipseCon 2008: Fundamentals of the Eclipse Modeling FrameworkEclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
EclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
Dave Steinberg
 
EMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
EMF Eclipse Modeling Framework 2nd Edition Dave SteinbergEMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
EMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
ymriszamek
 
Modeling With Eclipse @SoftShake 2011
Modeling With Eclipse @SoftShake 2011Modeling With Eclipse @SoftShake 2011
Modeling With Eclipse @SoftShake 2011
Mickael Istria
 
EMF - The off beat path
EMF - The off beat pathEMF - The off beat path
EMF - The off beat path
17thcamel
 
MDD and modeling tools research
MDD and modeling tools researchMDD and modeling tools research
MDD and modeling tools research
Roger Xia
 
Model Driven Development With Emf And Eclipse Link
Model Driven Development With Emf And Eclipse LinkModel Driven Development With Emf And Eclipse Link
Model Driven Development With Emf And Eclipse Link
Suresh Krishna Madhuvarsu
 
ALT
ALTALT
ALT
frolikat
 
What the heck is Eclipse Modeling and why should you care !
What the heck is Eclipse Modeling and why should you care !What the heck is Eclipse Modeling and why should you care !
What the heck is Eclipse Modeling and why should you care !
Cédric Brun
 
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the FutureEclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Tonny Madsen
 
Eclipse Summit 2008 Jcrm Demo V1.4
Eclipse Summit 2008 Jcrm Demo V1.4Eclipse Summit 2008 Jcrm Demo V1.4
Eclipse Summit 2008 Jcrm Demo V1.4
guestc06d27
 
JCR Mangement - Eclipse Summit 2008
JCR Mangement - Eclipse Summit 2008JCR Mangement - Eclipse Summit 2008
JCR Mangement - Eclipse Summit 2008
inovex GmbH
 
EMF Facet 0.1.0 - Nantes DemoCamp 2011
EMF Facet 0.1.0 - Nantes DemoCamp 2011EMF Facet 0.1.0 - Nantes DemoCamp 2011
EMF Facet 0.1.0 - Nantes DemoCamp 2011
Grégoire Dupé
 
Development of forms editors based on Ecore metamodels
Development of forms editors based on Ecore metamodelsDevelopment of forms editors based on Ecore metamodels
Development of forms editors based on Ecore metamodels
Mario Cervera
 
Pragmatic Model Driven Development using openArchitectureWare
Pragmatic Model Driven Development using openArchitectureWarePragmatic Model Driven Development using openArchitectureWare
Pragmatic Model Driven Development using openArchitectureWare
Michael Vorburger
 
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSEMODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
Anže Vodovnik
 
What every Eclipse developer should know about EMF - Tutorial at EclipseCon
What every Eclipse developer should know about EMF - Tutorial at EclipseConWhat every Eclipse developer should know about EMF - Tutorial at EclipseCon
What every Eclipse developer should know about EMF - Tutorial at EclipseCon
JonasHelming
 
What's New in MDT?
What's New in MDT?What's New in MDT?
What's New in MDT?
Kenn Hussey
 
Model-driven development and Code generation
Model-driven development and Code generationModel-driven development and Code generation
Model-driven development and Code generation
Pavel Vlasov
 
ITU - MDD - EMF
ITU - MDD - EMFITU - MDD - EMF
ITU - MDD - EMF
Tonny Madsen
 
Eclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Eclipse World 2007: Fundamentals of the Eclipse Modeling FrameworkEclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Eclipse World 2007: Fundamentals of the Eclipse Modeling Framework
Dave Steinberg
 
EclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
EclipseCon 2008: Fundamentals of the Eclipse Modeling FrameworkEclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
EclipseCon 2008: Fundamentals of the Eclipse Modeling Framework
Dave Steinberg
 
EMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
EMF Eclipse Modeling Framework 2nd Edition Dave SteinbergEMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
EMF Eclipse Modeling Framework 2nd Edition Dave Steinberg
ymriszamek
 
Modeling With Eclipse @SoftShake 2011
Modeling With Eclipse @SoftShake 2011Modeling With Eclipse @SoftShake 2011
Modeling With Eclipse @SoftShake 2011
Mickael Istria
 
EMF - The off beat path
EMF - The off beat pathEMF - The off beat path
EMF - The off beat path
17thcamel
 
MDD and modeling tools research
MDD and modeling tools researchMDD and modeling tools research
MDD and modeling tools research
Roger Xia
 
Model Driven Development With Emf And Eclipse Link
Model Driven Development With Emf And Eclipse LinkModel Driven Development With Emf And Eclipse Link
Model Driven Development With Emf And Eclipse Link
Suresh Krishna Madhuvarsu
 
What the heck is Eclipse Modeling and why should you care !
What the heck is Eclipse Modeling and why should you care !What the heck is Eclipse Modeling and why should you care !
What the heck is Eclipse Modeling and why should you care !
Cédric Brun
 
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the FutureEclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Eclipse Demo Camp 2010 - Eclipse e4 – The Status and the Future
Tonny Madsen
 
Eclipse Summit 2008 Jcrm Demo V1.4
Eclipse Summit 2008 Jcrm Demo V1.4Eclipse Summit 2008 Jcrm Demo V1.4
Eclipse Summit 2008 Jcrm Demo V1.4
guestc06d27
 
JCR Mangement - Eclipse Summit 2008
JCR Mangement - Eclipse Summit 2008JCR Mangement - Eclipse Summit 2008
JCR Mangement - Eclipse Summit 2008
inovex GmbH
 
EMF Facet 0.1.0 - Nantes DemoCamp 2011
EMF Facet 0.1.0 - Nantes DemoCamp 2011EMF Facet 0.1.0 - Nantes DemoCamp 2011
EMF Facet 0.1.0 - Nantes DemoCamp 2011
Grégoire Dupé
 
Development of forms editors based on Ecore metamodels
Development of forms editors based on Ecore metamodelsDevelopment of forms editors based on Ecore metamodels
Development of forms editors based on Ecore metamodels
Mario Cervera
 
Pragmatic Model Driven Development using openArchitectureWare
Pragmatic Model Driven Development using openArchitectureWarePragmatic Model Driven Development using openArchitectureWare
Pragmatic Model Driven Development using openArchitectureWare
Michael Vorburger
 
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSEMODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
MODEL DRIVEN ARCHITECTURE, CONTROL SYSTEMS AND ECLIPSE
Anže Vodovnik
 
What every Eclipse developer should know about EMF - Tutorial at EclipseCon
What every Eclipse developer should know about EMF - Tutorial at EclipseConWhat every Eclipse developer should know about EMF - Tutorial at EclipseCon
What every Eclipse developer should know about EMF - Tutorial at EclipseCon
JonasHelming
 
What's New in MDT?
What's New in MDT?What's New in MDT?
What's New in MDT?
Kenn Hussey
 
Model-driven development and Code generation
Model-driven development and Code generationModel-driven development and Code generation
Model-driven development and Code generation
Pavel Vlasov
 
Ad

Recently uploaded (20)

SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdfThe Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
The Evolution of Meme Coins A New Era for Digital Currency ppt.pdf
Abi john
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 

EclipseCon 2007: Effective Use of the Eclipse Modeling Framework

  • 1. Christian W. Damus, Kenn Hussey, Ed Merks and Dave Steinberg IBM Rational Software Ottawa and Toronto, Canada EMF, EMFT, and MDT Projects Effective Use of the Eclipse Modeling Framework https://w3-03.ibm.com/legal/ipl/iplsite.nsf/pages/wtts-trademarks+home
  • 2. Part 1: Introduction to the Eclipse Modeling Framework
  • 3. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 4. EMF Demo Quickly generate a working graphical editor to create and manipulate instances of a UML model
  • 5. What is EMF? A modeling & data integration framework Exploits the facilities offered in Eclipse to… Generate code without losing user customizations (merge) Automate important tasks (such as registering the runtime information) Improve extensibility Provide a UI layer What is an EMF “model”? Specification of your application’s data Object attributes Relationships (associations) between objects Operations available on each object Simple constraints (eg. cardinality) on objects and relationships Essentially it represents the class diagram of the application
  • 6. What does EMF Provide? From a model specification, EMF can generate efficient, correct, and easily customizable implementation code Out of the box, EMF provides support for Java ™ interfaces UML XML Schema EMF converts your models to Ecore (EMF metamodel) Tooling support within the Eclipse framework (UI, headless mode, Ant and standalone), including support for generating Eclipse-based and RCP editors Reflective API and dynamic model definition Persistence API with out of box support for XML/XMI (de)serialization of instances of a model And much more….
  • 7. Why EMF? EMF is middle ground in the modeling vs. programming worlds Focus is on class diagram subset of UML modeling (object model) Transforms models into Java code Provides the infrastructure to use models effectively in your application Very low cost of entry EMF is free and open source Full scale graphical modeling tool not required Reuses your knowledge of UML, XML Schema, or Java It’s real, proven technology (since 2002)
  • 8. EMF History First version was released in June, 2002 Originally based on MOF (Meta Object Facility) From OMG (Object Management Group) Abstract language and framework for specifying, constructing, and managing technology neutral metamodels EMF evolved based on experience supporting a large set of tools Efficient Java implementation of a practical subset of the MOF API 2003: EMOF defined (Essential MOF) Part of OMG’s MOF 2 specification; UML2 based EMF is approximately the same functionality Significant contributor to the spec; adapting to it
  • 9. Who is Using EMF Today? Eclipse projects Foundation for the Modeling Project: Graphical Modeling Framework (GMF), EMF Ontology Definition Metamodel (EODM), UML2… Other uses: Web Tools Platform (WTP), Test and Performance Tools Platform (TPTP), Business Intelligence and Reporting Tools (BIRT), Data Tools Platform (DTP), Visual Editor (VE)… Commercial offerings IBM, Borland, Oracle, Omondo, Versata, MetaMatrix, Bosch, Ensemble… Applied sciences Darmstadt University of Technology, Mayo Clinic College of Medicine, European Space Agency… Large open source community Over 1,000,000 download requests in 2006
  • 10. EMF at IBM Pervasive usage across product lines IBM ® Rational ® Software Architect IBM Rational Application Developer for WebSphere Software IBM WebSphere ® Integration Developer IBM WebSphere Application Server IBM Lotus ® Workplace Emerging technology projects: alphaWorks ® Emfatic Language for EMF Development (http://www.alphaworks.ibm.com/tech/emfatic) Model Transformation Framework (http://www.alphaworks.ibm.com/tech/mtf) XML Forms Generator (http://www.alphaworks.ibm.com/tech/xfg)
  • 11. What Have People Said About EMF? EMF represents the core subset that's left when the non-essentials are eliminated. It represents a rock solid foundation upon which the more ambitious extensions of UML and MDA can be built. – Vlad Varnica, OMONDO Business Development Director, 2002 EMF provides the glue between the modeling and programming worlds , offering an infrastructure to use models effectively in code by integrating UML, XML and Java. EMF thus fits well into [the] Model-Driven Development approach, and is critically important for Model-Driven Architecture , which underpins service-oriented architectures [SOA]. – Jason Bloomberg, Senior analyst for XML & Web services, ZapThink, 2003 EMF was chosen because it (a) provides a lightweight, pragmatic approach to modeling with very low entry cost and is thus suitable for rapid prototyping, (b) unifies key technologies such as Java and XML, and (c) integrates well into Eclipse. – Bruch, Bockisch, Schäefer, Mezini, Darmstadt Univ. of Technology, 2005 [As] a consultant with fiduciary responsibility to my customers, [...] given the enormous traction that Eclipse has gathered, we have to view the EMF metadata management framework as the de facto standard . – David Frankel, as seen in Business Process Trends, March 2005
  • 12. Creating the Ecore Model Representing the modeled domain in Ecore is the first step in using EMF Ecore can be created Directly using the EMF editors Through a graphical UI provided by external contributions By converting a model specification for which a Model Importer is available Model Importers available in EMF Java Interfaces UML models expressed in Rational Rose ® files XML Schema Choose the one matching your perspective or skills
  • 13. Model Importers Available in EMF Java Interfaces public interface PurchaseOrder { String getShipTo (); void setShipTo(String value); String getBillTo (); void setBillTo(String value); List<Item> getItems (); } public interface Item { String getProductName (); void setProductName(String value); int getQuantity (); void setQuantity(int value) float getPrice (); void setPrice(float value); }
  • 14. Model Importers Available in EMF UML Class Diagram
  • 15. Model Importers Available in EMF XML Schema <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <xsd:schema xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; targetNamespace=&quot;http://www.example.com/SimplePO&quot; xmlns:PO=&quot;http://www.example.com/SimplePO&quot;> <xsd:complexType name=&quot; PurchaseOrder &quot;> <xsd:sequence> <xsd:element name=&quot; shipTo &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; billTo &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; items &quot; type=&quot;PO:Item&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;/> </xsd:sequence> </xsd:complexType> <xsd:complexType name=&quot;Item&quot;> <xsd:sequence> <xsd:element name=&quot; productName &quot; type=&quot;xsd:string&quot;/> <xsd:element name=&quot; quantity &quot; type=&quot;xsd:int&quot;/> <xsd:element name=&quot; price &quot; type=&quot;xsd:float&quot;/> </xsd:sequence> </xsd:complexType> </xsd:schema>
  • 16. Unifying Java, XML and UML Technologies The Model Importers available in EMF were carefully chosen to integrate today’s most important technologies All three forms provide the same information Different visualization/representation The application’s “model” of the structure From a model definition, EMF can generate Java implementation code, including UI XML Schemas Eclipse projects and plug-in
  • 17. Typical EMF Usage Scenario Create an Ecore model that represents the domain you are working on Import UML (e.g. Rose .mdl file) Import XML Schema Import annotated Java interfaces Create Ecore model directly using EMF's Ecore editor or a graphical editor Generate Java code for model Prime the model with instance data using generated EMF model editor Iteratively refine model (and regenerate code) and develop Java application You will use the EMF generated code to implement the use cases of your application Optionally, use EMF.Edit to build customized user interface
  • 18. EMF and Java 5.0 EMF 2.3 exploits the capabilities of Java 5.0 Generics Typesafe enums Annotations Enhanced for loop Autoboxing EMF 2.3 provides a 5.0-targeted runtime that can only be run on a Java 5.0 or later VM The code generator can also produce application code that runs on a 1.4 VM against the EMF 2.2.x runtime This is a recognition that Java 5.0 is the way forward, but the transition need not be painful for the user
  • 19. EMF and Java 5.0 Want to know more about Java 5.0 and EMF? Modeling Generics with Ecore Tuesday, 11:10 am Grand Ballroom D Java 5: A Developer’s Experience Thursday, 10:10 am Room 203-204
  • 20. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 21. EMF Architecture EMF Runtime EMF Tools Core Edit Codegen Model Editor Application Generates Eclipse Platform
  • 22. EMF Components EMF Core Ecore metamodel Model change notification & validation Persistence and serialization Reflection API Runtime support for generated models EMF Edit Helps integrate models with a rich user interface Used to build editors and viewers for your model Includes default reflective model editor EMF Codegen Code generator for core and edit based components Extensible model importer/exporter framework
  • 23. EMF Tools: Model Import and Generation Generator Features: Customizable JSP-like templates (JET) JDT-integrated, command-line, or Ant Fully supports regeneration and merge I M P O R T GENERATE Ecore Model UML XML Schema Java model Java model Java edit Java editor* * Eclipse IDE-integrated or RCP-based
  • 24. EMF Model Importers UML Rational Rose .mdl file Eclipse UML2 project provides importer for .uml2 Annotated Java Java interfaces representing modeled classes Javadoc annotations using @model tags to express model properties not captured by method declarations Lowest cost approach XML Schema Describes the data of the modeled domain Provides richer description of the data, which EMF exploits Ecore model (*.ecore file) Just creates the generator model (discussed later) Also handles EMOF (*.emof)
  • 25. Ecore Model Creation An Ecore model is created within an Eclipse project via a wizard Input: one of the model specifications from the previous slide Output: modelname.ecore Ecore model file in XMI format Canonical form of the model modelname.genmodel A “generator model” for specifying generator options Contains decorators for Ecore model elements, providing details that would otherwise pollute the model (e.g. target directories for code generation) EMF code generator is an EMF .genmodel editor Automatically kept in synch with .ecore file
  • 26. Ecore Model Editor A generated (and customized) EMF editor for the Ecore model Create, delete, etc. model elements (EClass, EAttribute, EReference, etc.) using pop-up actions in the editor's tree Set names, etc. in the Properties view
  • 27. Ecore Model Editor A graphical editor is a better approach GMF Ecore Diagram Example (http://www.eclipse.org/gmf/) Omondo EclipseUML (http://www.omondo.com/)
  • 28. EMF Generator Similar layout to Ecore model editor Automatically keeps in synch with .ecore changes Generate code with pop-up menu actions Generate Model Code Generate Edit Code Generate Editor Code Generate Test Code Generate All Code generation options in Properties view Generator > Reload to reload .genmodel and .ecore files from original model form
  • 29. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 30. The Ecore (Meta) Model Ecore is EMF's model of a model Also called a “metamodel” Persistent representation is XMI
  • 32. Partial List of Ecore Data Types Ecore data types are serializable and custom data types are supported java.lang.Float EFloatObject java.lang.Object EJavaObject java.lang.Boolean EBooleanObject byte[ ] EByteArray java.lang.String EString float EFloat char EChar boolean EBoolean Java Primitive Type or Class Ecore Data Type
  • 33. Ecore Model for Purchase Orders is represented in Ecore as
  • 34. Purchase Order Ecore XMI Alternate serialization format is EMOF (Essential MOF) XMI Part of OMG Meta Object Facility (MOF) 2.0 standard (http://www.omg.org/docs/ptc/04-10-15.pdf) <eClassifiers xsi:type=&quot;ecore:EClass&quot; name=&quot; PurchaseOrder &quot;> <eReferences name=&quot; items &quot; eType=&quot;#//Item&quot; upperBound=&quot;-1&quot; containment=&quot;true&quot;/> <eAttributes name=&quot; shipTo &quot; eType=&quot;ecore:EDataType http:...Ecore#//EString&quot;/> <eAttributes name=&quot; billTo &quot; eType=&quot;ecore:EDataType http:...Ecore#//EString&quot;/> </eClassifiers>
  • 35. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 36. Code Generation EMF framework is lightweight Generated code is clean, simple, efficient EMF can generate Model implementation UI-independent edit support Editor and views for Eclipse IDE-integrated or RCP application JUnit test skeletons Manifests, plug-in classes, properties, icons, etc.
  • 37. Generated Model Code Interface and implementation for each modeled class Includes get/set accessors for attributes and references Usage example public interface PurchaseOrder extends EObject { String getShipTo (); void setShipTo (String value); String getBillTo (); void setBillTo (String value); EList<Item> getItems (); } order .getItems().add( item );
  • 38. Generated Model Code Factory to create instances of model objects Package class provides access to metadata Also generated: switch utility, adapter factory base, validator, custom resource, XML processor POFactory factory = POFactory.eINSTANCE ; PurchaseOrder order = factory .createPurchaseOrder(); POPackage poPackage = POPackage.eINSTANCE ; EClass itemClass = poPackage. getItem (); //or POPackage.Literals.ITEM EAttribute priceAttr = poPackage. getItem_Price (); //or itemClass.getEStructuralFeature( POPackage.ITEM__PRICE ) //or POPackage.Literals.ITEM__PRICE
  • 39. Generated Edit/Editor Code Viewing/editing code divided into two parts UI-independent code Item providers (adapters) Item provider adapter factory UI-dependent code Model creation wizard Editor Action bar contributor Advisor (RCP) By default each part is placed in a separate Eclipse plug-in
  • 40. Java 5.0 Constructs For a new model, EMF 2.3 targets the compiler compliance level specified by the containing project (or the workspace default) To generate code with Java 5.0 constructs for an existing model, use the “Compliance Level” property on the GenModel
  • 41. Summary of Generated Artifacts Model Interfaces and classes Type-safe enumerations Package (metadata) Factory Switch utility Adapter factory base Validator Custom resource XML Processor Edit (UI independent) Item providers Item provider adapter factory Editor Model Wizard Editor Action bar contributor Advisor (RCP) Tests Test cases Test suite Stand-alone example Manifests, plug-in classes, properties, icons...
  • 42. Regeneration and Merge Hand-written code can be added to generated code and preserved during regeneration This merge capability has an Eclipse dependency, so is not available standalone All generated classes, interfaces, methods and fields include @generated marker in their Javadoc To replace generated code: Remove @generated marker Or include additional text, e.g. @generated NOT Methods without @generated marker are left alone during regeneration
  • 43. Regeneration and Merge Extend (vs. replace) generated method through redirection Append “Gen” suffix to the generated method's name /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public String getName Gen () { return name; } public String getName () { return format(getNameGen()); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public String getName () { return name; }
  • 44. The Code Generation Process Java Code Model Importer JET Simplified version UML Java Model ? XML Schema GenModel Ecore
  • 45. The Code Generation Process Java Code Merged Java Code Model Importer JET JMerge Generated Java Code Full version UML Java Model ? XML Schema GenModel Ecore
  • 46. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 47. EMF Runtime Persistence and serialization of model data Proxy resolution and demand load Automatic notification of model changes Bi-directional reference handshaking Dynamic object access through a reflective API Runtime environments Eclipse Full IDE RCP Standalone Java
  • 48. Persistence and Serialization Serialized data is referred to as a resource Data can be spread out among a number of resources in a resource set One resource is loaded at a time, even if it has references to objects in other resources in the resource set Proxies exist for objects in other resources Lazy or demand loading of other resources as needed A resource can be unloaded
  • 49. Resource Set Context for multiple resources that may have references among them Usually just an instance of ResourceSetImpl, or a customized subclass Provides factory method for creating new resources in the set: Also provides access to the registries, URI converter, and default load options for the set ResourceSet rs = new ResourceSetImpl (); URI uri = URI.createFileURI(&quot;C:/data/po.xml&quot;); Resource resource = rs. createResource (uri);
  • 50. Resource Factory Registry Returns a resource factory for a given type of resource Based on the URI scheme or filename extension Determines the type of resource, hence format for save/load For models created from XML Schema, the generated custom resource factory implementation should be registered to ensure schema-conformant serialization When running as a plug-in under Eclipse, EMF provides an extension point for registering resource factories Generated plugin.xml registers generated resource factory against a package specific extension (e.g. “po”) Global registry: Resource.Factory.Registry.INSTANCE Consulted if no registered resource factory found locally Resource.Factory.Registry reg = rs. getResourceFactoryRegistry (); reg. getExtensionToFactoryMap ().put(&quot; xml &quot;, new XMLResourceFactoryImpl ());
  • 51. Package Registry Returns the package identified by a given namespace URI Used during loading to access the factory for creating instances Global registry: EPackage.Registry.INSTANCE Consulted if no registered package found locally Running in Eclipse, EMF provides an extension point for globally registering generated packages Even standalone, a package automatically registers itself when accessed: EPackage.Registry registry = rs. getPackageRegistry (); registry.put( POPackage.eNS_URI , POPackage.eINSTANCE ); POPackage poPackage = POPackage.eINSTANCE;
  • 52. Resource Container for objects that are to be persisted together Convert to and from persistent form via save() and load() Access contents of resource via getContents() EMF provides XMLResource implementation Other, customized XML resource implementations, provided, too (e.g. XMI, Ecore, EMOF) URI uri = URI.createFileURI(&quot;C:/data/po.xml&quot;); Resource resource = rs.createResource(uri); resource. getContents ().add(p1); resource. save (null); <PurchaseOrder> <shipTo>John Doe</shipTo> <next>p2.xml#p2</next> </PurchaseOrder>
  • 53. Proxy Resolution and Demand Load PurchaseOrder p2 = p1. getNext (); p1 p1.xml next p2 p2.xml proxyURI=“ p2.xml #p2” next proxyURI=“p2.xml#p2” next <PurchaseOrder> <shipTo>John Doe</shipTo> <next> p2.xml#p2 </next> </PurchaseOrder> p1.xml
  • 54. Model Change Notification Every EMF object is also a Notifier Send notification whenever an attribute or reference is changed EMF objects can be “observed” in order to update views and dependent objects Adapter poObserver = ... purchaseOrder. eAdapters ().add(poObserver);
  • 55. Model Change Notification Observers or listeners in EMF are called adapters An adapter can also extend class behavior without subclassing For this reason they are typically added using an AdapterFactory PurchaseOrder purchaseOrder = ... AdapterFactory somePOAdapterFactory = ... Object poExtensionType = ... if (somePOAdapterFactory. isFactoryForType (poExtensiontype)) { Adapter poAdapter = somePOAdapterFactory. adapt (purchaseOrder, poExtensionType); ... }
  • 56. Model Change Notification Efficient notification in “set” methods Checks for listeners before creating and sending notification public String getShipTo() { return shipTo; } public void setShipTo(String newShipTo) { String oldShipTo = shipTo; shipTo = newShipTo; if (eNotificationRequired()) eNotify(new ENotificationImpl(this, ... ); }
  • 57. Bidirectional Reference Handshaking public interface PurchaseOrder { PurchaseOrder getNext (); void setNext (PurchaseOrder value); PurchaseOrder getPrevious (); void setPrevious (PurchaseOrder value); } Invariant imposed by the bidirectional reference: po.getNext().getPrevious() == po
  • 58. Bidirectional Reference Handshaking p1. setNext (p3); p2 p1 p2 p3 previous next next previous next previous next previous change notification
  • 59. Bidirectional Reference Handshaking This multi-step procedure is implemented using InternalEObject methods: eInverseRemove() eInverseAdd() Framework list implementations and generated setters directly invoke them on target objects as needed Notifications are accumulated using a NotificationChain and fired off at the end They are not used to implement the handshaking
  • 60. Reflection All EMF classes implement interface EObject Provides an efficient API for manipulating objects reflectively Used by the framework (e.g., serialization/deserialization, copy utility, generic editing commands, etc.) Also key to integrating tools and applications built using EMF public interface EObject { EClass eClass (); Object eGet (EStructuralFeature sf); void eSet (EStructuralFeature sf, Object val); ... }
  • 61. Reflection Example Setting an attribute using generated API: Using reflective API: PurchaseOrder po = ... po. setBillTo (&quot;123 Elm St.&quot;); EObject po = ... EClass poClass = po.eClass(); po. eSet (poClass.getEStructuralFeature(&quot;billTo&quot;), &quot;123 Elm St.&quot;);
  • 62. Reflective Performance Efficient generated switch-based implementation of reflective methods public Object eGet (int featureID, ...) { switch (featureID) { case POPackage.PURCHASE_ORDER__SHIP_TO: return getShipTo (); case POPackage.PURCHASE_ORDER__BILL_TO: return getBillTo (); ... } }
  • 63. Reflection Benefits Reflection allows generic access to any EMF model Similar to Java’s introspection capability Every EObject (that is, every EMF object) implements the reflection API An integrator need only know your model! A generic EMF model editor uses the reflection API Can be used to edit any EMF model
  • 64. Dynamic EMF Ecore models can be defined dynamically in memory No generated code required Dynamic implementation of reflective EObject API provides same runtime behavior as generated code Also supports dynamic subclasses of generated classes All EMF model instances, whether generated or dynamic, are treated the same by the framework A dynamic Ecore model can be defined by Instantiating model elements with the Ecore API Loading from a .ecore file
  • 65. Dynamic EMF Example Model definition using the Ecore API EPackage poPackage = EcoreFactory.eINSTANCE. createEPackage (); poPackage. setName (&quot;po&quot;); poPackage. setNsURI (&quot;http://www.example.com/PurchaseOrder&quot;);    EClass poClass = EcoreFactory.eINSTANCE. createEClass (); poClass. setName (&quot;PurchaseOrder&quot;); poPackage. getEClassifiers ().add(poClass);   EAttribute billTo = EcoreFactory.eINSTANCE. createEAttribute (); billTo. setName (&quot;billTo&quot;); billTo. setEType (EcorePackage.eINSTANCE. getEString ()); poClass. getEStructuralFeatures ().add(billTo); ... EObject po = EcoreUtil.create(poClass); po.eSet(billTo,&quot;123 Elm St.&quot;);
  • 66. XML Processor Simplified API for loading and saving XML Handles resource set, registries, etc. under the covers Can automatically create a dynamic Ecore representation of a schema Load/save instance documents without generating code Manipulate the objects using reflective EObject API URI schemaURI = ... String instanceFileName = ... XMLProcessor processor = new XMLProcessor (schemaURI); Resource resource = processor. load (instanceFileName, null); EObject documentRoot = resource.getContents.get(0);
  • 67. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 68. Recording Changes EMF provides facilities for recording the changes made to instances of an Ecore model Change Model An EMF model for representing changes to objects Directly references affected objects Includes “apply changes” capability Change Recorder EMF adapter Monitors objects to produce a change description (an instance of the change model)
  • 70. Change Recorder Can be attached to EObjects, Resources, and ResourceSets Monitors changes to the objects and their contents trees Produces a description of the changes needed to return to the original state (a reverse delta) Result: a change description with one change, setting billTo to “123 Elm St.” PurchaseOrder order = ... order.setBillTo(&quot;123 Elm St.&quot;); ChangeRecorder recorder = new ChangeRecorder(); recorder. beginRecording (Collections.singleton(order)); order.setBillTo(&quot;456 Cherry St.&quot;); ChangeDescription change = recorder. endRecording ();
  • 71. Applying Changes Given a change description, the change can be applied: ChangeDescription.apply() consumes the changes, leaving the description empty ChangeDescription.applyAndReverse() reverses the changes, leaving a description of the changes originally made (the forward delta) The model is always left in an appropriate state for applying the resulting change description
  • 72. Example: Transaction Capability If any part of the transaction fails, undo the changes ChangeRecorder changeRecorder = new ChangeRecorder(resourceSet); try { // modifications within resource set } catch (Exception e) { changeRecorder. endRecording (). apply (); }
  • 73. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 74. Validation Framework Model objects validated by external EValidator Detailed results accumulated as Diagnostics Essentially a non-Eclipse equivalent to IStatus Records severity, source plug-in ID, status code, message, other arbitrary data, and nested children public interface Evalidator { boolean validate (EObject eObject, DiagnosticChain diagnostics, Map Context); boolean validate (EClass eClass, EOjbect eObject, DiagnosticChain, diagnostics, Map context); boolean validate (EDataType eDataType, Object value, DiagnosticChain diagnostics, Map context); ... }
  • 75. Invariants and Constraints Invariant Defined directly on the class, as an operation with <<inv>> stereotype Stronger statement about validity than a constraint Constraint Externally defined for the class via a method on the validator
  • 76. Generated EValidator Implementations Generated for each package that defines invariants or constraints Dispatches validation to type-specific methods For classes, a validate method is called for each invariant and constraint Method body must be hand coded for invariants and named constraints
  • 77. Schema-Based Constraints In XML Schema, named constraints are defined via annotations: Also, constraints can be defined as facets on simple types, and no additional coding is required Constraint method implementation generated <xsd:annotation> <xsd:appinfo source=&quot;http://www.eclipse.org/emf/2002/Ecore&quot; ecore:key=&quot;constraints&quot;>VolumeDiscount</xsd:appinfo> </xsd:annotation> <xsd:simpleType name=&quot;SKU&quot;> <xsd:restriction base=&quot;xsd:string&quot;> <xsd:pattern value=&quot;\d{3}-[A-Z]{2}&quot;/> </xsd:restriction> </xsd:simpleType>
  • 78. Framework EValidator Implementations EObjectValidator validates basic EObject constraints: Multiplicities are respected Proxies resolve All referenced objects are contained in a resource Data type values are valid Used as base of generated validators and directly for packages without additional constraints defined
  • 79. Framework EValidator Implementations Diagnostician walks a containment tree of model objects, dispatching to package-specific validators Diagnostician.validate() is the usual entry point Obtains validators from its EValidator.Registry Diagnostician validator = Diagnostician.INSTANCE ; Diagnostic diagnostic = validator. validate (order); if (diagnostic.getSeverity() == Diagnostic.ERROR) { // handle error } for (Diagnostic child : diagnostic.getChildren()) { // handle child diagnostic }
  • 80. Agenda EMF in a Nutshell EMF Components The Ecore Metamodel Code Generation, Regeneration and Merge The EMF Runtime Recording Changes Validation Summary
  • 81. Summary EMF is low-cost modeling for the Java mainstream Boosts productivity and facilitates integration Mixes modeling with programming to maximize the effectiveness of both
  • 82. Summary EMF provides… A metamodel (Ecore) with which your domain model can be specified Your model can be created from UML, XML Schema or annotated Java interfaces Generated Java code Efficient and straightforward Code customization preserved Persistence and Serialization Resource-based serialization Proxy resolution and demand loading Default resource implementation is XMI (XML metadata interchange), but can be overridden
  • 83. Summary EMF provides… Model change notification is built in Just add adapters (observers) where needed Reflection and dynamic EMF Full introspection capability Simple change recording and roll-back Extensible validation framework Standalone runtime support A UI-independent layer for viewing and editing modeled data (EMF.Edit)
  • 84. Part 2: Advanced Features of the Eclipse Modeling Framework
  • 85. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 86. Working with Resources and ResourceSets Working with proxies Identifying proxies Using the Validation Framework to detect unresolved proxies Using “fragment queries” to handle unresolved proxies Cross-Resource Containment Inverse References Resource Tips & Tricks Unloading Tracking modification Am I loading something?
  • 87. Persistence and Serialization Review Serialized data is referred to as a resource Data can be spread out among a number of resources in a resource set One resource is loaded at a time, even if it has references to objects in other resources in the resource set Proxies exist for objects in other resources Lazy or demand loading of other resources as needed A resource can be unloaded
  • 88. Identifying Proxies In some scenarios it may be important to know up-front what are the proxies referenced by a given object Check whether the user has everything that will be necessary to load the model Extract missing resources from the repository Decide whether loading a specific object is a long or short operation org.eclipse.emf.ecore.util.EcoreUtil.ProxyCrossReferencer A CrossReferencer that finds proxies without resolving them For each object in a given context (resource, resource set, EObject, collection), checks if the referenced objects are in the same resource or not
  • 89. Going Deeper: EcoreUtil’s CrossReferencers Utility classes that find “uses” of an object Also the data structures that hold the objects they find A CrossReferecer is a java.util.Map On each Map.Entry Key: reference target Value: list of EStructuralFeature.Setting with all the source object-feature pairs referencing the keyed target
  • 90. Going Deeper: EStructuralFeature.Setting Interface that represents the value held by a feature of an EObject Exposes all the feature-related methods of EObject eGet, eSet, eIsSet, and eUnset
  • 91. Going Deeper: Types of Reference Containment Reference Has an “implicit” opposite (eObject.eContainer()) Container Reference An explicit reference defined as the opposite of a containment reference Cross-Reference May or may not have an opposite Any reference can refer to an EObject located in either the same or different resource
  • 92. EcoreUtil.ProxyCrossReferencer public static void printProxiesDetails(ResourceSet resourceSet ) { int counter = 0; Map<EObject, Collection<EStructuralFeature.Setting>> map = ProxyCrossReferencer .find(resourceSet); for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> entry : map.entrySet()) { EObject proxyEObject = entry. getKey (); System.out.println (&quot;&quot; + ++counter + &quot;. &quot; + EcoreUtil.getURI(proxyEObject)); System.out.println (&quot;Is Proxy: &quot; + proxyEObject.eIsProxy()); for (EStructuralFeature.Setting setting : entry. getValue ()) { System.out.println (&quot;\tFeature: &quot; + setting. getEStructuralFeature ().getName()); EObject eObject = setting. getEObject (); EStructuralFeature nameFeature = eObject.eClass().getEStructuralFeature(&quot;name&quot;); if (nameFeature != null) { System.out.println (&quot;\tEObject.getName(): &quot; + eObject.eGet(nameFeature)); } } } } 1. uri3.xmi#/0 Is Proxy: true Feature: home EObject.getName(): john
  • 93. Validating Proxies The validation framework can be used to validate proxies The EObjectValidator checks if all the referenced objects of a given EObject are resolved The proxy references are resolved during the validation If a proxy is broken, the validation produces a Diagnostic with EObjectValidator. EOBJECT__EVERY_PROXY_RESOLVES as its error code
  • 94. Validating Proxies public static void validateProxies(EObject eObject) { Diagnostic diagnostic = Diagnostician .INSTANCE. validate (eObject); if (diagnostic.getSeverity() == Diagnostic.ERROR) { if ( hasEveryProxyResolvesCode (diagnostic)) { System.out.println (&quot;Broken proxies found!&quot;); return; } } System.out.println (&quot;Proxies are fine.&quot;); } public static boolean hasEveryProxyResolvesCode (Diagnostic diagnostic) { if (diagnostic. getCode () == EObjectValidator. EOBJECT__EVERY_PROXY_RESOLVES ) return true; for (Diagnostic childDiagnostic : diagnostic.getChildren()) { return hasEveryProxyResolvesCode (childDiagnostic); } return false; }
  • 95. Handling Broken Proxies Your application can provide a mechanism to handle broken proxies by Reporting the error to the user Avoiding use of the object(s) that could not be resolved Recovering the missing object(s) EMF doesn’t provide such a mechanism but provides hooks to help you implement one Fragment query capability is one of these hooks
  • 96. Stepping Back: Uniform Resource Identifier (URI) A formatted string that serves as an identifier for a resource Specification: Definition: http://www.ietf.org/rfc/rfc1630.txt Generic Syntax: http://www.ietf.org/rfc/rfc2396.txt Syntax: Generic [ scheme : ] scheme-specific-part [ # fragment ] Hierarchical [ scheme : ][ // authority ][ path ][ ? query ][ # fragment ] Used in EMF to identify a resource, an object in a resource, or an Ecore package (namespace URI)
  • 97. Fragment Queries The idea is to “decorate” the fragment portion of a URI with details that further describe the referenced object The description can be used by a service to locate the object or to enrich an error message to be presented to the user Query data Added to the fragment portion of the object’s URI Must be at the end of the URI fragment portion Is delimited by “?” Example: file:/c:/dir/library.xmi #//@books.0?Book.ISBN.0131425420? Fragment Query URI Fragment
  • 98. Saving Fragment Queries If you are using a XMLResource to serialize your objects Override the getURIFragmentQuery(Resource, EObject) method of org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl to return the query that should be serialized for the given EObject Override the createXMLHelper() method of org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl to return an instance of your XMLHelper The getURIFragmentQuery(…) method returns the string that is used as the “query” The string should not contain the delimiter character ( ? ) A null string indicates that there is no query The characters must be valid URI fragment characters (as defined by the specification)
  • 99. Going Deeper: org.eclipse.emf.ecore.xmi.XMLHelper Interface used by the default resource implementations Not used by clients Single place where the methods used to save and load objects are located Simplifies customizations
  • 100. Using Fragment Queries EMF doesn’t enforce the use of fragment queries Reasonable approach: Load an object Try to resolve its proxies Identify the remaining (broken) proxies Use the fragment query of the broken proxies to either report the problem to the user or recover the missing objects
  • 101. Cross-Resource Containment Allows an object hierarchy to be persisted across multiple resources eObject.eResource() may be different from eObject.eContainer().eResource() Must be explicitly enabled The containment reference has to be set to resolve proxies Also, on generated models, the value of the “Containment Proxies” generator model property has to be set to ‘true’
  • 102. Enabling Cross-Resource Containment EReference houses = EcoreFactory.eINSTANCE.createEReference(); houses.setName(&quot;houses&quot;); houses.setEType(house); houses.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); houses.setContainment(true); houses. setResolveProxies ( true ); person.getEStructuralFeatures().add(houses); Dynamic Model Generated Model
  • 103. Cross-Resource Containment { Library library = LibFactory.eINSTANCE.createLibrary(); Book book = LibFactory.eINSTANCE.createBook(); library .getBooks().add(book); System.out.println (library.eResource() + &quot; - &quot; + book.eResource()); Resource libraryResource = new ResourceImpl(URI.createURI(&quot; lib &quot;)); libraryResource .getContents().add( library ); System.out.println (library.eResource().getURI() + &quot; - “ + book.eResource().getURI()); Resource bookResource = new ResourceImpl(URI.createURI(&quot; book &quot;)); bookResource .getContents().add( book ); System.out.println (library.eResource().getURI() + &quot; - &quot; + book.eResource().getURI()); bookResource .getContents().remove( book ); System.out.println (library.eResource().getURI() + &quot; - &quot; + book.eResource().getURI()); } null - null lib - lib lib - book lib - lib
  • 104. EcoreUtil Methods for Cross-Resource Containment When the containment tree is spread across multiple files, one may be interested in differentiating the “local” children of an object from children in other resources The *Proper* methods available in EcoreUtil only deal with the “local” children of a containment tree All children Local children
  • 105. Inverse References Sometimes it may be handy to retrieve the opposite of a unidirectional association end For example, the use case you are implementing requires a navigation that was not anticipated when the model was defined EMF provides two mechanisms CrossReferencer ECrossReferenceAdapter
  • 106. Going Deeper: Associations and References An association between two classes allows their instances to “communicate” with each other Each navigable end of an association is represented by an EReference in Ecore If the association is bidirectional, it will be represented by two references, r1 and r2 where r1.getEOpposite() == r2 && r2.getEOpposite() == r1 Associations References
  • 107. Using a CrossReferencer Dynamically computes a map with the target object and the list of settings that “refer” to it This computation may be a long operation depending on the number of objects The map represents a snapshot of the state of the objects As the objects change, the settings’ values may become inconsistent with the map Requires a context to compute the map The context can be a collection of EObjects, a resource, or a resource set, or a combination of these Objects that are not in the scope of the context won’t be available in the map
  • 108. Using a CrossReferencer { Library library = LibFactory.eINSTANCE.createLibrary(); Book book = LibFactory.eINSTANCE.createBook(); book.setTitle(&quot;EMF&quot;); Person dave = LibFactory.eINSTANCE.createPerson(); library .getBooks().add( book ); library .getWriters().add( dave ); book .getWriters().add( dave ); Map<EObject, Collection<EStructuralFeature.Setting>> map = EcoreUtil.CrossReferencer .find(Collections.singleton( library )); Collection<EStructuralFeature.Setting> settings = map.get(dave); if (settings != null) { for (EStructuralFeature.Setting setting : settings) { if (setting. getEObject () == book && setting. getEStructuralFeature () == LibPackage.Literals. BOOK__WRITERS ) { System.out.println (&quot;Found it. The book is \&quot;&quot; + book.getTitle() + &quot;\&quot;&quot;); } } } } Found it. The book is &quot;EMF&quot;
  • 109. Using the ECrossReferenceAdapter A special adapter that Attaches itself to all objects in a containment hierarchy May pose a memory footprint problem depending on the number of objects Keeps a CrossReferencer in sync with the state of the objects The application can determine and change the context used when computing the map
  • 110. Using the ECrossReferenceAdapter { Library library = LibFactory.eINSTANCE.createLibrary(); ECrossReferenceAdapter adapter = new ECrossReferenceAdapter (); library.eAdapters().add( adapter ); Book book = LibFactory.eINSTANCE.createBook(); book.setTitle(&quot;EMF&quot;); Person dave = LibFactory.eINSTANCE.createPerson(); library .getBooks().add( book ); library .getWriters().add( dave ); book .getWriters().add( dave ); Collection<EStructuralFeature.Setting> settings = adapter. getNonNavigableInverseReferences (dave); for (EStructuralFeature.Setting setting : settings) { if (setting. getEObject () == book && setting. getEStructuralFeature () == LibPackage.Literals. BOOK__WRITERS ) { System.out.println (&quot;Found it. The book is \&quot;&quot; + book.getTitle() + &quot;\&quot;&quot;); } } } Found it. The book is &quot;EMF&quot;
  • 111. Resource Tips & Tricks Unloading a resource Resource.unload() EMF’s default implementation performs the following steps: Sets the loaded attribute to false; Caches an iterator with all the proper contents of all objects held by the resource Clears the resource’s content, error and warning lists Turns each object returned by the iterator into a proxy and clears its adapter list Fires a notification Feature ID = Resource. RESOURCE__IS_LOADED You may also remove the resource from the resource set
  • 112. Resource Tips & Tricks Tracking modification Resource.setTrackingModification(boolean) When activated, EMF’s default implementation performs the following steps: Instantiates an Adapter and registers it on all proper objects The adapter calls Resource.setModified(boolean) after receiving a notification Registers the adapter on any object added to the resource and deregisters it from objects that are removed When deactivated, the default implementation removes the adapter from the objects You can manually define what is the isModified state of a resource
  • 113. Resource Tips & Tricks Am I loading something? Resource.Internal.isLoading() Every Resource is supposed to implement the Resource.Internal interface When a resource is being loaded the isLoading() method returns true
  • 114. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 115. Generating Customized Code The EMF code generator can be customized in various ways to meet the needs of your application There are different levels of customization Generator Options Dynamic Templates Generator Extension
  • 116. Generator Options The EMF code generator provides a number of options which can have a significant effect on the kind of code that is generated from the default templates Suppress Interfaces Suppress EMF Metadata Root Extends Interface Suppress EMF Types Suppress EMF Model Tags
  • 117. Generator Options All can be adjusted as properties of the GenModel element, the root object in the generator
  • 118. Suppress Interfaces /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library extends EObject { /** * Returns the value of the ‘Name' attribute. * @model * @generated */ String getName(); ... } /** * A representation of the model object * 'Library'. * @model * @generated */ public class Library extends EObjectImpl implements EObject { /** * The default value of the 'Name' attribute. * @model * @generated */ protected static final NAME_EDEFAULT = null; ... }
  • 119. Suppress Interfaces Improves performance since dispatch through an interface is slower and less likely to be in-lined by a JIT compiler Reduces byte code footprint somewhat Can only be used for models with no multiple inheritance
  • 120. Suppress EMF Metadata Helps produce an API with no visible EMF dependencies, i.e. a &quot;pure&quot; API /** * The Package for the model. * @model kind=&quot;package&quot; * @generated */ public interface LibraryPackage extends EPackage { /** * The package name. * @generated */ String eNAME = &quot;library&quot;; ... /** * The meta object id for the 'Book' class. * @generated */ int BOOK = 0; ... } /** * The Package for the model. * @model kind=&quot;package&quot; * @generated */ public class LibraryPackageImpl extends EPackageImpl { /** * The package name. * @generated */ String eNAME = &quot;library&quot;; ... }
  • 121. Root Extends Interface Helps produce an API with no visible dependencies on EMF, or an API that visibly participates in another framework ‘ Root Extends Class’ and ‘Root Implements Interface’ are also available (classes must implement InternalEObject) /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library { ... } /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library extends EObject { ... }
  • 122. Suppress EMF Model Tags Helps produce an API with no visible dependencies on EMF /** * A representation of the model object * 'Library'. * @generated */ public interface Library extends EObject { ... /** * Returns the value of the Writers containment * reference list. * @generated */ EList<Writer> getWriters(); ... } /** * A representation of the model object * 'Library'. * @model * @generated */ public interface Library extends EObject { ... /** * Returns the value of the Writers containment * reference list. * @model containment=&quot;true&quot; * type=&quot;org.eclipse.example.library.Writer&quot; * @generated */ EList<Writer> getWriters(); ... }
  • 123. Suppress EMF Types EList, EMap, and EObject suppressed Applies to feature, operation and parameter types Helps produce an API with no visible dependencies on EMF /** * Returns the value of the Writers containment * reference list. * @model containment=&quot;true“ * type=&quot;org.eclipse.exasmple.library.Writer&quot; * @generated */ List <Writer> getWriters(); /** * Returns the value of the Writers containment * reference list. * @model containment=&quot;true&quot; * type=&quot;org.eclipse.example.library.Writer&quot; * @generated */ EList <Writer> getWriters();
  • 124. Dynamic Templates The content of the templates used by the EMF code generator can be changed or replaced by enabling dynamic templates Set the value of the ‘Dynamic Templates’ generator model property to ‘true’ Set the value of the ‘Template Directory’ generator model property to the location of the custom templates Dynamic templates can be customized in three ways Replacement Insertions Overrides
  • 125. Template Replacement Copy default template to the dynamic template directory (with the same name and relative location) and modify as desired Modified template is compiled dynamically and used in place of the default template Must keep in sync with changes in default templates (“clone and own”)…
  • 126. Template Insertions Can insert content into default templates via insertion points identified using JET @include directive (fail=“silent”) Dynamic template includes default template; insertions are included and compiled dynamically, result is used in place of the default template By convention, insertions are placed in a folder named after the including template and end with a .insert.*jet extension A number of insertion points have been defined for some commonly customized EMF templates (i.e. Class.javajet, ItemProvider.javajet, TestCase.javajet)
  • 127. Template Overrides Can override content of default templates via override points identified using JET @include directive (fail=“alternative”) Dynamic template includes default template; overrides are included and compiled dynamically, result is used in place of the default template By convention, overrides are placed in a folder named after the including template and end with a .override.*jet extension A number of override points have been defined for some commonly customized EMF templates (i.e. Class.javajet, ResourceFactoryClass.javajet, TestCase.javajet)
  • 128. Template Insertions and Overrides Simplified example from Class.javajet: <%@ include file=&quot;Class/genOperation.override.javajetinc&quot; fail=&quot;alternative&quot; %> <%@ start %> public <%=genOperation.getImportedType()%> <%=genOperation.getName()%>(...) { <%if (genOperation.hasBody()) {%> <%=genOperation.getBody(genModel.getIndentation(stringBuffer))%> ... <%} else {%> <%@ include file=&quot;Class/genOperation.TODO.override.javajetinc&quot; fail=&quot;alternative&quot; %> <%@ start %> // TODO: implement this method throw new UnsupportedOperationException(); <%@ end %> <%}%> } <%@ include file=&quot;Class/genOperation.insert.javajetinc&quot; fail=&quot;silent&quot; %> <%@ end %>
  • 129. Generator Extension EMF’s generator is extensible Code generation is performed by visiting the elements in the model and invoking templates to generate artifacts for each element Control over this process is delegated to GeneratorAdapters via one or more GeneratorAdapterFactory Additional adapter factories can be plugged into the generator to create adapters that generate additional artifacts
  • 130. Generator Extension Contributing adapters via an extension point: Adapters can be added directly, or via an adapter factory A generic adapter factory is instantiated for each adapter added directly, so it’s more efficient to add multiple adapters via a factory <extension point=&quot; org.eclipse.emf.codegen.ecore.generatorAdapters &quot;> < adapterFactory class=&quot;com.example.generator.MyGeneratorAdapterFactory&quot;/> < adapter modelClass=&quot;GenModel&quot; class=&quot;com.example.generator.MyGenModelGeneratorAdapter&quot;/> </extension>
  • 131. Generator Model Extension It is possible, but not advised, to extend the generator model by subclassing its elements New attributes can be added to support additional code generation options These attributes can be exposed as properties in the generator UI by registering a specialized adapter factory via the org.eclipse.emf.edit.itemProviderAdapterFacotries extension point Protected members of GenModel elements are not considered API: you may have to adapt to changes in the base implementation! A better way to introduce new code generation options is using generator annotations
  • 132. Going Deeper: GenAnnotations GenAnnotations can be added to any instance of GenBase, i.e. any object in a GenModel containment tree (including GenAnnotations themselves) GenBase provides two methods to work with GenAnnotations getGenAnnotations() getGenAnnotation(String source) A GenAnnotation, like its close relative EAnnotation, defines A source attribute, which is typically used to store a URI representing the type of the annotation A details map attribute to store name-value pairs Containment and non-containment references to EObjects
  • 133. Going Deeper: GenAnnotations The GenAnnotations are usually hidden in the Generator You can unhide them by checking &quot;Show Annotations&quot; in the &quot;Generator&quot; menu
  • 134. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 135. Performance/Memory Overhead EMF provides a number of mechanisms that can be used to tune the performance and/or memory overhead of your model implementation Code Generator Options Boolean Flags Virtual Feature Delegation Minimal Reflective Methods XMLResource Options
  • 136. Boolean Flags Generates code that uses (a) consolidated bit field(s) instead of separate fields to represent the values of Boolean attributes and whether unsettable features are set Set the value of the ‘Boolean Flags Field’ generator model property to the name of the bit field(s) to be generated or reused Set the value of the ‘Boolean Flags Reserved Bits’ generator model property to the number of bits in the field(s) that are reserved (e.g. used by parent classes) Helps reduce memory overhead for models with a large number of Boolean attributes or unsettable features
  • 137. Virtual Feature Delegation Generates code that uses a single, dynamically-allocated array field and associated index field(s) instead of separate fields to represent the values of non-primitive features Set the value of the ‘Feature Delegation’ generator model property to ‘Virtual’ Helps reduce memory overhead for models with a large number of features that are often “sparsely” used
  • 138. Minimal Reflective Methods Generates reflective methods that delegate to super , i.e. they delegate switching for any non-matching features to the superclass implementation for dispatching Set the value of the ‘Minimal Reflective Methods’ generator model property to ‘true’ (default) Helps reduce memory (byte code) overhead for models with a large number of inherited features May increase performance overhead for models with deep class hierarchies
  • 139. XMLResource Options XMLResource offers a set of options that can be used to tweak load and save behavior The options are passed to the resource’s save and load methods as entries in a map The key is the constant that represents the option Each option requires an appropriate value
  • 140. XMLResource Load Options OPTION_DEFER_IDREF_RESOLUTION Option value: Boolean Defers resolving references within a resource until the whole document has been parsed OPTION_USE_PARSER_POOL Option value: org.eclipse.emf.ecore.xmi.XMLParserPool Provides a parser pool, from which SAXParser instances are created and reused OPTION_USE_XML_NAME_TO_FEATURE_MAP Option value: java.util.Map Enables sharing the cache of mappings between qualified XML names (namespace + local name) and corresponding Ecore features across invocations of load(…), or even among resources
  • 141. XMLResource Load Options OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List Specifies a list as a place holder for caching information during the subsequent saving of XML documents OPTION_USE_DEPRECATED_METHODS Option value: Boolean Use methods that were deprecated in EMF The default value is Boolean.TRUE
  • 142. XMLResource Save Options OPTION_FLUSH_THRESHOLD Option value: Integer Specifies a maximum number of characters to allow in the output stream before flushing it OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List Provides a placeholder to cache information about structure of the model (using qualified XML names as a key for caching information) OPTION_CONFIGURATION_CACHE Option value: Boolean Enables caching and reusing generic data in repeated save operations, avoiding the cost of reinitializing the data
  • 143. XMLResource Save Options OPTION_FORMATTED Option value: Boolean Disables formatting of documents, omitting whitespaces and line brakes, to improve the performance of saving and, subsequently, loading the resulting document OPTION_USE_FILE_BUFFER Option value: Boolean Enables accumulating output during serialization in a temporary file, rather than an in-memory buffer
  • 144. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 145. Importers and Exporters Java model Annotated Java Model Importer EMF Model Exporter Java model UML Java model XML Schema Java model Ecore Java model ? Java model ? Java model XML Schema Java model XML Schema for XMI
  • 146. Model Importers A Model Importer (aka an importer) is responsible for creating an Ecore model from the description of a modeled domain Each importer knows how to handle a specific format of description An importer is also expected to create the generator model (.genmodel file) for the Ecore Model (.ecore file) EMF provides importers that handle the following formats Rational Rose models XML Schemas Annotated Java Interfaces Ecore and EMOF files
  • 147. Model Exporters A Model Exporter (aka exporter) is able to read an Ecore model and generate another description of the same modeled domain An exporter typically uses the information described in the Generator Model to accomplish its purposes EMF provides two exporters XML Schema XML Schema for XMI EMF also provides an HTML exporter example, which uses JET to produce a package summary
  • 148. Going Deeper: Why is the Generator Model so important? The generator model acts as a decorator for an Ecore model It provides details that would pollute the model, such as the Qualified name of an EPackage Prefix for package-related class names Actual location of the model, edit, editor, and test source folders When a modeled domain is converted into an EMF model, the importer may be able to capture some generator model details and store them in a .genmodel file The Java package of the annotated Java interfaces Referenced XML Schemas that may or may not be already represented by Ecore models The generator model is useful to an exporter because It can be used to persist details about the exported artifact Some details may be important to properly describe the modeled domain
  • 149. Using Importers and Exporters The importers and exporters are presented to the user as pages of a standard EMF wizard The registered importers are presented during the execution of the new EMF model or EMF project wizards The list of exporters is shown when the “Export Model…” action is invoked on a .genmodel file The motivation of this design is to let the importers and exporters decide the input that the user needs to provide Each implementation has total control over the number of pages of the wizard and their content The Rose and XML Schema importers are also available as Eclipse applications and Ant tasks
  • 150. Contributing an Importer via an Extension Point The wizard must be a class that implements EMF’s IModelImporterWizard interface Defines the setters that will be used by the new EMF model and project wizards to communicate the details about the model specification being imported <extension point=&quot; org.eclipse.emf.importer.modelImporterDescriptors &quot;> <modelImporterDescriptor id =&quot;com.mycompany.ModelImporterDescriptor.XYZ&quot; name=&quot;XYZ class model&quot; extensions=&quot;xyz&quot; wizard =&quot;com.mycompany.ImportWizard&quot;/> </extension>
  • 151. Contributing an Exporter via an Extension Point The wizard must be a class that implements Eclipse’s IWorkbenchWizard interface The first time the wizard is presented to the user, the method init(IWorkbench, IStructuredSelection) is invoked and the selection argument is either an IFile that contains the generator model or an instance of GenModel <extension point=&quot; org.eclipse.emf.importer.modelExporterDescriptors &quot;> <modelExporterDescriptor id =&quot;com.mycompany.ModelExporterDescriptor.XYZ&quot; name=&quot;XYZ class model&quot; wizard =&quot;com.mycompany.ExportWizard&quot;/> </extension>
  • 152. Contributing Importers and Exporters via Global Registries The idea is to add the importer/exporter description to the appropriate list ModelImporterManager.INSTANCE.getModelConverterDescriptors() ModelExporterManager.INSTANCE.getModelConverterDescriptors() The importer and exporter descriptions are quite similar, which led to the creation of a common parent interface
  • 153. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 154. Backward/Forward Compatibility EMF provides mechanisms that can be used to support migration of data between different versions of a model (or between two different models, for that matter): Use Ecore2Ecore and Ecore2XML to define a mapping between the different model(s) (versions) Use Ecore2XMLExtendedMetaData with save/load options to handle unrecognized data Use a resource handler to pre/post-process data that cannot be mapped automatically Source and target models must have different namespace URIs and XML references must not be based on feature names
  • 155. Ecore2Ecore Mappings Describe a mapping between two Ecore models Can be created from an Ecore (*.ecore) model via the ‘Map To Ecore…’ context menu item in the Package Explorer or Resource Navigator Typically used as a development-time artifact (only) Can include one-to-one, one-to-many, many-to-one, many-to-many, and one-sided mappings Only one-to-one and one-sided (one-to-none, none-to-one) mappings are useful for data migration
  • 156. Ecore2XML Mappings Describe a mapping between an Ecore model and its XML representation Can be generated from an Ecore2Ecore (*.ecore2ecore) model via the ‘Generate Ecore to XML Mapping…’ context menu item in the Package Explorer or Resource Navigator Often used as a run-time artifact (in conjunction with Ecore2XMLExtendedMetaData) Can include one-to-one and many-to-one mappings, but only the former are useful for data migration
  • 157. Ecore2XMLExtendedMetaData Can be used with the OPTION_EXTENDED_META_DATA save/load option defined on XMLResource to affect how data are serialized/deserialized Will consult registered Ecore2XML mappings to determine the XML representation of objects my.y my.x x_2_y.ecore2xml
  • 158. OPTION_RECORD_UNKNOWN_FEATURE Load option defined on XMLResource Will record data for unrecognized types and features in an extension map (XMLResource#getEObjectToExtensionMap()) on the resource Recorded data will be serialized again when the resource is saved (unless the entries in the map have been cleared) my.x my.y y => x
  • 159. Resource Handlers Interface XMLResource.ResourceHandler defines callbacks that can be implemented to do special processing before/after a resource is loaded/saved Used with OPTION_RESOURCE_HANDLER save/load option defined on XMLResource Can support backward compatibility by extracting data from a resource’s extension map after it is loaded Can support forward compatibility by inserting data into a resource’s extension map before it is saved
  • 160. Enabling Data Migration Create a package registry and add entries which map the source namespace URI and target Ecore model location to the target package Create an Ecore2XML registry and add an entry which maps the source namespace URI to the Ecore2XML mapping Create an instance of Ecore2XMLExtendedMetaData based on the package and Ecore2XML registries; pass this extended metadata as the value for the XMLResource.OPTION_EXTENDED_META_DATA load/save option
  • 161. Enabling Data Migration Pass Boolean.TRUE as the value for the XMLResource.OPTION_RECORD_UNKNOWN_FEATURE load option If required, pass an implementation of XMLResource.ResourceHandler as the value for the XMLResource.OPTION_RESOURCE_HANDLER load/save option
  • 162. Agenda Working with Resources and ResourceSets Customizing the Code Generator Tuning for Performance and/or Memory Footprint Importers and Exporters Supporting Backward and Forward Compatibility Summary
  • 163. Summary We have seen examples of how flexible and extensible the Eclipse Modeling Framework is Hopefully you have gained greater insight into how some of the more “advanced” features of EMF can be exploited to meet your application’s needs
  • 164. Part 3: Eclipse Modeling Framework Technologies – Query, Transaction, Validation
  • 165. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 166. What is EMFT? A collection of components that “add on” to EMF to provide value-added capabilities for rich applications Currently includes: Validation – a flexible framework for contributing 3 rd -party constraints to model validation Query – an SQL-like Java API for querying EMF resources Transaction – a transaction protocol for concurrent access to EMF resources CDO, Teneo – object-relational mappings for persistence of EMF resources in RDBMSes JET Editor – a rich editor for JET templates
  • 167. What was EMFT? Formerly in EMFT: OCL – an implementation of the Object Constraint Language for Ecore and UML metamodels; now a component of MDT EODM – an implementation of the Ontology Definition Metamodel for Ecore; now a component of MDT JET (a.k.a. JET2) – next generation of the Java Emitter Templates; now a component of M2T This tutorial will explore the Validation, Query, and Transaction components with a little OCL added for flavour
  • 168. What does the Validation Framework Provide? Extensibility: Constraint providers contribute constraints from any source they deem fit, including the plugin.xml, constraints embedded in models, or external models Constraint parsers contribute support for constraint specification languages. Out of the box, the framework implements Java and OCL support. Traversal strategies contribute knowledge of the model structure and how to discover its extent to validate it Constraint categories and bindings help to organize constraints and activate them in specific applications Validation listeners are notified whenever validation occurs, to provide an appropriate response from the application
  • 169. What does the Validation Framework Provide? Invocation (Triggers) “Batch” validation: initiated by the user or by the system on some important event, validates all or a selected subset of a model “Live” validation: initiated automatically by the system to validate a set of changes performed during some transaction. The semantics of “transaction” are defined by the client Constraints can specify which particular changes trigger them (by feature and event type) Support for OCL constraints EMFT Validation uses the OCL component of the MDT project to provide out-of-box support for specifying constraints using OCL
  • 170. What does the Query Framework Provide? A convenient Java API for querying an EMF-based model The API is designed to look and feel like SQL, with SELECT and UPDATE statements, FROM clauses, etc. Offers a wide array of reusable and recombinable predicate objects for specifying WHERE clause conditions Supports nested and compound queries Easily customizable for special requirements in traversing models, etc. Support for OCL Provides predicate classes that specify WHERE conditions as OCL constraints (with context or, optionally, context-free)
  • 171. What does the Transaction API Provide? A transactional editing environment Safe read and write access to EMF resources from multiple concurrent threads Commit protocol providing mechanisms for ensuring model integrity: Validation of the changes performed during the transaction (constraints) using the Validation Framework Pre-commit listeners proactively performing concomitant changes (triggers) to maintain consistency of dependencies Automatic rollback of changes on failure to validate or complete triggers Supports transaction nesting
  • 172. What does the Transaction API Provide? Read/write transactions Give a thread exclusive access to a ResourceSet for the purpose of modifying its content Ensure that other threads do not observe interim (uncommitted) states of the data (“dirty reads”) Read-only transactions Protect against threads concurrently initializing concrete state of the ResourceSet (such as duplicate resolution of proxies or duplicate initialization of ELists) Can be shared cooperatively by multiple reading threads
  • 173. What does the Transaction API Provide? Change events Commit of a transaction sends a ResourceSetChangeEvent to interested listeners, with a summary of the changes that the transaction performed Changes are sent as a single batch, and only on successful commit, so that UI refreshes etc. don’t get any “noise” Integration with Eclipse Workbench APIs Support for delegating the EMF CommandStack to an IOperationHistory Leverages the IUndoContext to support separate undo/redo “stacks” where independent changes occur in a single ResourceSet
  • 174. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 175. Constraint Providers Constraint providers are of two flavours: static and dynamic Static providers declare their constraints in the plugin.xml of a client plug-in of the constrained model Dynamic providers obtain constraints from an arbitrary source at run-time Both kinds of providers can declare constraint categories and include their constraints in categories defined by any provider Categories are hierarchical namespaces for constraints Constraints are grouped by category in the preference page
  • 176. Static Constraint Provider <extension point=&quot; org.eclipse.emf.validation.constraintProviders &quot;> < category name =&quot;Library Constraints&quot; id =&quot;com.example.library&quot;> <constraintProvider> < package namespaceUri =&quot;http:///www.eclipse.org/Library/1.0.0&quot;/> <constraints categories =&quot;com.example.library&quot;> <constraint lang =&quot;Java&quot; class =&quot;com.example.constraints.UniqueLibraryName&quot; severity =&quot;WARNING&quot; mode =&quot;Batch&quot; name=&quot;Library Must have a Unique Name&quot; id=&quot;com.example.library.LibraryNameIsUnique&quot; statusCode=&quot;1&quot;> <description>Libraries have unique names.</description> <message>{0} has the same name as another library.</message> < target class =&quot;Library&quot;/> </constraint> </constraints> </constraintProvider> </extension>
  • 177. Dynamic Constraint Provider Registered by name of a class implementing the IModelConstraintProvider interface Indicate the packages for which they supply constraints Biggest difference is the absence of a <constraints> element System can optionally cache the provided constraints <extension point=&quot; org.eclipse.emf.validation.constraintProviders &quot;> < category name =&quot;Library Constraints&quot; id =&quot;com.example.library&quot;> <constraintProvider class =&quot;com.example.MyConstraintProvider&quot; cache =&quot;false&quot;> < package namespaceUri =&quot;http:///www.eclipse.org/Library/1.0.0&quot;/> </constraintProvider> </extension>
  • 178. Dynamic Constraint Provider A dynamic constraint provider implements the IModelConstraintProvider interface A descriptor supplies meta-data about a constraint The validation algorithm is supplied by the constraint object in the validate() method
  • 179. Constraints Descriptor provides: ID and localizable name Evaluation mode Target EClasses Triggering events (live) Severity, error message Categorization Enabled state Much of this information appears in the preference page Users can choose which constraints to activate
  • 180. Evaluation Modes Batch validation is usually explicitly requested by the user, via a menu action or toolbar button Live validation is performed automatically as changes are made to EMF resources Live constraints indicate which specific changes trigger them <constraint mode =&quot;Live&quot; … > <description>Libraries have unique names.</description> <message>{0} has the same name as: {1}.</message> <target class=&quot;Library&quot;> < event name =&quot;Set&quot;> < feature name =&quot;name&quot;/> </ event > </target> </constraint>
  • 181. Validation Service Evaluation of constraints is performed via the Validation Service The service provides validators corresponding to the available evaluation modes By default, batch validation includes live constraints, also, for completeness
  • 182. Validation Service To validate one or more elements, in batch mode, simply create a new validator and ask it to validate: List objects = myResource.getContents(); // objects to validate // create a validator IValidator validator = ModelValidationService.getInstance() . newValidator (EvaluationMode. BATCH ); // use it! IStatus results = validator. validate (objects); if (!results.isOK()) { ErrorDialog.openError(null, &quot;Validation&quot;, &quot;Validation Failed&quot;, results); }
  • 183. Validation Service Live validation does not validate objects, but rather Notification s indicating changes to objects List< Notification > notifications = … ; // some changes that we observed // create a validator IValidator validator = ModelValidationService.getInstance() .newValidator(EvaluationMode. LIVE ); // use it! IStatus results = validator.validate( notifications ); if (!results.isOK()) { ErrorDialog.openError(null, &quot;Validation&quot;, &quot;Validation Failed&quot;, results); }
  • 184. Creating Constraints Specifying a constraint doesn’t necessarily require any code Requires the OCL component of the MDT project <constraint lang=&quot; OCL &quot; mode=&quot;Batch&quot; … > <description>Libraries have unique names.</description> <message>{0} has the same name as: {1}.</message> <target class=&quot;Library&quot;/> <![CDATA[ Library.allInstances()->forAll(l | l <> self implies l.name <> self.name) ]]> </constraint>
  • 185. Creating Constraints Sometimes the easiest or best way to formulate a constraint is in Java Java constraints extend the AbstractModelConstraint class The validation context provides the validate() method with information about the validation operation
  • 186. Validation Context Provides the element being validated (the target) Indicates the current evaluation mode (live or batch) In case of live invocation, provides the changed feature and the event type Allows constraints to cache arbitrary data for the duration of the current validation operation Provides convenient methods for reporting results Provides the ID of the constraint that is being invoked
  • 187. Creating Constraints public class LibraryNameIsUnique extends AbstractConstraint { public IStatus validate (IValidationContext ctx) { Library target = (Library) ctx. getTarget (); // object to validate // does this library have a unique name? Set<Library> libs = findLibrariesWithName(target.getName()); if (libs.size() > 1) { // report this problem against all like-named libraries ctx. addResults (libs); // don’t need to validate these other libraries libs.remove(target); ctx. skipCurrentConstraintFor (libs); return ctx.createFailureStatus(new Object[] { target, libs}); } return ctx. createSuccessStatus (); } }
  • 188. Listening for Validation Events Every validation operation executed by the Validation Service generates an event The event indicates the kind of validation performed, on what objects, and what were the results (incl. severity) Listeners registered on the extension point are lazily initialized when their selection criteria are met <extension point=&quot; org.eclipse.emf.validation.validationListeners &quot;> < listener class =&quot;com.example.validation.ProblemsReporter&quot;> < clientContext id =&quot;com.example.MyClientContext&quot;/> </listener> </extension>
  • 189. Reporting Problems Problems are reported as IConstraintStatus objects. A status knows: The constraint that was violated The objects that violated it The severity and error message, as usual for an IStatus The marker utility encodes all of this information in a problem marker on the appropriate resource, to show in the Problems view
  • 190. Reporting Problems public class ProblemsReporter implements IValidationListener { public void validationOccurred (ValidationEvent event) { if (event. matches (IStatus.WARNING | IStatus.ERROR)) { // fabricate a multi-status for the MarkerUtil to consume List results = event. getValidationResults (); IConstraintStatus multi = new MultiStatus( &quot;com.example.MyPlugin&quot;, 1, (IStatus[])results.toArray(new IStatus[results.size()]), &quot;Problems were found by validation&quot;, null); try { // create problem markers on the appropriate resources MarkerUtil.createMarkers (multi); } catch ( CoreException e ) { // creation of problem markers failed for some reason MyPlugin.getLog().log(e.getStatus()); } } } }
  • 191. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 192. Query Statements SELECT statements filter the objects provided by a FROM clause according to the conditions specified in the WHERE clause SELECT s are IEObjectSource s, so they can be used in FROM clauses to nest queries UPDATE statements use a SET clause to update the objects provided by the FROM clause (filtered, of course, by the WHERE clause)
  • 193. The FROM Clause Uses EMF’s tree iterators to walk the objects being queried Optionally specifies an EObjectCondition filter Search scope is encapsulated in an IEObjectSource provides objects via an iterator. The FROM descends into the contents of these objects if it is a hierarchical IteratorKind
  • 194. The WHERE Clause The WHERE clause specifies a single filter condition This filter condition can be arbitrarily complex Filters can be combined in innumerable ways using the common boolean operators The IN filter detects whether an object is an element of a supplied set (as in SQL)
  • 195. The WHERE Clause The framework provides a condition on the model type of objects Can also filter for objects that are identical to some target ( EObjectInstanceCondition )
  • 196. The WHERE Clause The framework provides conditions that filter objects based on values of their features In particular, the EObjectReferencerCondition filters for cross-references to a particular object
  • 197. The WHERE Clause: Condition Policies For multi-valued structural features, the ConditionPolicy determines whether a Condition must match all values or just any value Correspond to the relational  (for-all) and  (exists) quantifiers
  • 198. The WHERE Clause: Prune Handlers Just as with EMF’s tree iterators, a query’s iteration over its scope can be pruned Any EObjectCondition can have a PruneHandler that determines whether the search tree can be pruned This allows the query to skip over entire sub-trees when a condition knows that it will never be satisfied for any of the contents of the current object The default prune handler in most cases is NEVER which, as the name implies, never prunes
  • 199. The WHERE Clause: Other Conditions The framework includes a variety of conditions for working with primitive-valued EAttribute s Including strings, booleans, and numbers of all kinds Adapters convert inputs to the required data type Default implementations simply cast, assuming that the values already conform Can be customized to convert values by whatever means is appropriate
  • 200. OCL Conditions OCL can be used to specify WHERE clause conditions Only available when the OCL component of MDT is installed An OCLConstraintCondition specifies a boolean-valued expression (i.e., a constraint) that selects those elements for which the expression is true OCL expressions can be contextful or context-free
  • 201. The UPDATE Statement The UPDATE statement behaves much like a SELECT , except that it passes its result objects through the client-supplied SET clause The result of the UPDATE is the subset of the selected objects for which the SET clause returned true (indicating that they were, in fact, modified)
  • 202. SELECT Query in Action Queries can be used for anything from simple search functions to complex structural analysis They can even be used to implement validation constraints! IQueryResult result = new SELECT ( new FROM (res.getContents()), new WHERE (new EObjectAttributeValueCondition ( EXTLibraryPackage.Literals.WRITER__NAME, new StringRegularExpressionValue (&quot;.*Da.*&quot;)))).execute(); for (EObject next : result .getEObjects()) { Writer writer = (Writer) next; System.out.println (“Found “ + writer.getName()); } Found Dave Steinberg Found Christian Damus
  • 203. SELECT Query with OCL Condition Context-free OCL conditions are applied to any element on which they can be parsed IQueryResult result = new SELECT( new FROM(res.getContents()), new WHERE(new OCLConstraintCondition ( &quot; self.books->isEmpty() &quot;, null /* no EClass implies context-free */))).execute(); for (EObject next : result.getEObjects()) { String label = ((IItemLabelProvider) adapterFactory.adapt( next, IItemLabelProvider.class)).getText(next); System.out.println (&quot;Found &quot; + label); } Found Library New Library Found Writer Unpublished Author
  • 204. UPDATE Query in Action IQueryResult result = new UPDATE ( new FROM(res.getContents()), new WHERE(new OCLConstraintCondition( &quot;Employee->forAll(e | e.manager <> self)&quot;, EXTLibrary.Literals.EMPLOYEE)), new SET () { public boolean set(EObject eObject) { Employee emp = (Employee) eObject; emp. setSalary (emp.getSalary() * 1.05)); return true ; // updated this one }}).execute(); for (EObject next : result .getEObjects()) { Employee emp = (Employee) next; System.out.println (“Updated “ + emp.getFirstName() + &quot; &quot; + emp.getLastName()); } Updated Ed Merks Updated Dave Steinberg Updated Kenn Hussey Updated Christian Damus
  • 205. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 206. What is a Transaction? A transaction is a discrete unit of work in a resource set This work may be reading and writing the resource set contents or simply reading Transactions provide model integrity guarantees Isolation of concurrent threads to prevent data corruption Validation of changes on commit, rolling back (undoing those changes) automatically when data integrity is violated Automatic execution of triggers on commit, to proactively maintain data integrity This is not a concurrent transactional environment Transactions on multiple threads execute in strictly serial order
  • 207. What is a Transaction? Transactions in a resource set are managed by a TransactionalEditingDomain Read/write transactions are created by execution of commands on the domain’s TransactionalCommandStack Read-only transactions are created by execution of Runnable s via TransactionalEditingDomain::runExclusive() Most clients will never need to interact directly with Transaction objects, but only with the editing domain
  • 208. Creating Transactional Editing Domains Transactional editing domains are created by factories Use the TransactionalEditingDomain.Factory.INSTANCE shared instance to create a private domain for your editor To share one domain instance amongst multiple editors in an application, register a domain ID Add your editing domain instance to the TransactionalEditingDomain.Registry.INSTANCE Or, register it statically on the editingDomains extension point, specifying a factory for the registry to create it on demand <extension point=&quot; org.eclipse.emf.transaction.editingDomains &quot;> < domain id =&quot;com.example.MyEditingDomain&quot; factory =&quot;com.example.domain.MyCustomFactory&quot;/> <!– factory is optional; implied default is the shared instance --> </extension>
  • 209. Obtaining the Editing Domain Any editor that needs to access the registered editing domain simply gets it from the registry It is lazily created, using the associated factory, on first access static final String DOMAIN_ID = “ com.example.MyEditingDomain ”; public void init(IEditorSite site, IEditorInput input) throws PartInitException { // get our editing domain domain = TransactionalEditingDomain. Registry.INSTANCE .getEditingDomain(DOMAIN_ID); // load our input resource String fileName = ((IFileEditorInput) input).getFile() .getLocation(); resource = domain. loadResource (fileName); }
  • 210. Creating Read/Write Transactions To do work in a read/write transaction, simply execute a Command on the TransactionalCommandStack Just like using a regular EMF Editing Domain If the transaction needs to roll back, it will be undone automatically and will not be appended to the stack In order to find out when rollback occurs, use the TransactionalCommandStack::execute(Command, Map) method, which throws RollbackException , instead of using CommandStack::execute(Command) This method also accepts a map of options to configure the transaction that will be created (more on options, later)
  • 211. RecordingCommands The RecordingCommand class is a convenient command implementation for read/write transactions Uses the change information recorded (for possible rollback) by the transaction to “automagically” provide undo/redo TransactionalCommandStack stack; stack. execute (new RecordingCommand () { protected void doExecute () { Iterator iter = resource.getAllContents(); while (iter.hasNext()) { // changes are determined on-the-fly Object next = iter.next(); if (next instanceof Library) { ((Library) next).getBooks().add( LibraryFactory.eINSTANCE.createBook()); } } }}, Collections.EMPTY_MAP);
  • 212. Transaction Options The TransactionalCommandStack::execute() method accepts a map of options defined by the Transaction interface that determine how changes occurring during the transaction are handled: OPTION_NO_NOTIFICATIONS : changes are not included in post-commit change events OPTION_NO_TRIGGERS : changes are not included in pre-commit change events OPTION_NO_VALIDATION : changes are not validated OPTION_NO_UNDO : changes are not recorded for undo/redo and rollback. Use with extreme caution!
  • 213. Transaction Options (continued from previous slide) OPTION_UNPROTECTED : implies OPTION_NO_UNDO , OPTION_NO_VALIDATION , and OPTION_NO_TRIGGERS . In addition, permits writing to the resource set even in an otherwise read-only context. Use with even more extreme caution! The CommandStack::undo() and ::redo() methods use the following options for the undo/redo transaction: OPTION_NO_UNDO : because we are undoing or redoing a previous recording, there is no need to record anew OPTION_NO_TRIGGERS : triggers performed during execution were recorded and are automatically undone; any additional changes would be inappropriate OPTION_NO_VALIDATION : there is no need to validate a reversion to a previous state of the data
  • 214. Transaction Options The pre-defined options only apply to read/write transactions Permitted on read-only transactions but have no effect Extensions of the transaction API can define custom options TransactionalCommandStack stack; Library library; // don’t tell the UI that we are changing the library name stack. execute ( SetCommand.create(domain, library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;Secret Name&quot;), Collections.singletonMap( Transaction. OPTION_NO_NOTIFICATIONS , Boolean.TRUE));
  • 215. Creating Read-Only Transactions To read the contents of the resource set safely, use the runExclusive() API: TransactionalEditingDomain domain; domain. runExclusive (new Runnable () { public void run () { Iterator iter = resource.getAllContents(); while (iter.hasNext()) { Object next = iter.next(); if (next instanceof Library) { Library lib = (Library) next; System.out.println (lib.getName() + &quot; inventory: &quot; + lib.getBooks().size() + &quot; books&quot;); } } }}, Collections.EMPTY_MAP); Main Branch inventory: 3033 books West Branch inventory: 2570 books South Branch inventory: 1318 books
  • 216. Transaction Sharing Read-only transactions on multiple threads can be interleaved by cooperatively yielding their read lock Recommended for long-running read operations Call TransactionalEditingDomain::yield() to yield read access to other threads waiting for read-only transactions Yielding thread waits until other threads return read access to it either by finishing their transactions or by yielding Yielding is fair: read access is always passed to the thread that has waited longest Write access is not shared in this way Readers cannot yield to writers Writers cannot yield to any others
  • 217. Transaction Sharing final TransactionalEditingDomain domain; final IProgressMonitor monitor; // acquire read transaction on this thread domain. runExclusive (new Runnable () { public void run() { while (moreToRead()) { // … do a bunch of reading … readSomeStuff(); // checking the progress monitor is a good opportunity to // yield to other readers if (monitor.isCancelled()) { forgetIt(); break; } domain. yield (); // just returns if no readers waiting } }});
  • 218. Transaction Sharing A thread that owns a transaction can lend it to another thread using a PrivilegedRunnable The privileged runnable takes over the transaction for the duration of its run() method Can be used to share read-only and read-write transactions Ideal for runnables that need to access the resource set and the UI thread at the same time: Pass the privileged runnable to Display.syncExec(Runnable) API to run on the UI thread Must only be used with synchronous inter-thread communication such as syncExec The originator thread loses the transaction during the runnable
  • 219. Transaction Sharing TransactionalEditingDomain domain; final org.eclipse.swt.widgets.List bookList; // acquire read transaction on this thread domain. runExclusive (new Runnable () { public void run() { // hand it off to the UI thread to read the library and update // the list widget Display.syncExec (domain. createPrivilegedRunnable ( new Runnable() { public void run () { // the UI thread now has the transaction List<String> bookTitles = new ArrayList<String>(); for (Book book : library.getBooks) { bookTitles.add(book.getTitle()); } } // the UI thread gives up the transaction }));
  • 220. Change Listeners EMF provides an Adapter mechanism to notify listeners when objects change In a transactional environment, though, we can end up reacting to changes only to find that they are reverted when a transaction rolls back Enter the ResourceSetListener Post-commit event notifies a listener of all of the changes, in a single batch, that were committed by a transaction If a transaction rolls back, no event is sent because there were no changes There are exceptions for changes that are not (and need not be) undone, such as resource loading and proxy resolution
  • 221. Change Listeners ResourceSetChangeEvent provides the changes that occurred Transaction additionally has a ChangeDescription summarizing the changes Listeners can declare filters to receive only events of interest to them ResourceSetListenerImpl is a convenient base class providing no-ops for the listener call-backs
  • 222. Change Listeners Resource set listeners are added to the transactional editing domain Listeners can be registered statically against an editing domain ID Ensures that the listener is attached as soon as the domain comes into being Resolves the problem of timing the addition of listeners domain. addResourceSetListener (new MyListener ()); <extension point=&quot; org.eclipse.emf.transaction.listeners &quot;> < listener class =&quot;com.example.MyListener&quot;> < editingDomain id =&quot;com.example.MyEditingDomain&quot;/> </listener> </extension>
  • 223. Post-Commit Listeners A post-commit listener just overrides ResourceSetListenerImpl.resourceSetChanged() DemultiplexingListener implements this by dispatching the notifications one by one to the handleNotification() method class MyListener extends ResourceSetListenerImpl { public void resourceSetChanged (ResourceSetChangeEvent event) { System.out.println(&quot;Domain &quot; + event .getEditingDomain().getID() + &quot; changed &quot; + event .getNotifications().size() + &quot; times&quot;); } } class MyDemuxedListener extends DemultiplexingListener { protected void handleNotification (TransactionalEditingDomain domain, Notification notification) { System.out.println(&quot;Domain &quot; + domain .getID() + &quot; changed: &quot; + notification .getNotifier()); } }
  • 224. Post-Commit Listeners Advantages of the ResourceSetChangedEvent include: Listeners know that the changes are permanent Notifications can be processed efficiently as an aggregate Don’t need to worry about dependency on “future” changes No further changes can occur while the change event is being dispatched Listeners are invoked in read-only transactions, so that they can safely read the resource set while analyzing the changes Listeners need to be aware that notifications are delayed relative to the timing of the changes Notifications are only received after all changes are complete Any given notification may not correspond to the current state of the resource set, depending on subsequent changes
  • 225. Pre-Commit Listeners Before a transaction closes, pre-commit listeners are notified of the changes performed Listeners can provide additional changes, in the form of commands, to be appended to the transaction As with post-commit listeners, the pre-commit listener is invoked in a read-only transaction, so it does not make changes “directly” These commands implement proactive model integrity, as do triggers in RDBMS. Hence the term “trigger command” Trigger commands are executed in a nested transaction This procedure is recursive: the nested transaction also invokes pre-commit listeners when it commits
  • 226. Pre-Commit Listeners class MyListener extends ResourceSetListenerImpl { MyListener() { // only interested in changes to Library objects super(NotificationFilter. createNotifierTypeFilter ( EXTLibraryPackage.Literals.LIBRARY)); } public Command transactionAboutToCommit (ResourceSetChangeEvent event) { List commands = new ArrayList(); Iterator iter = event.getNotifications().iterator(); while (iter.hasNext()) { Notification next = (Notification) iter.next(); Library library = (Library) next.getNotifier(); if (library.getName() == null) commands.add( SetCommand.create ( event.getEditingDomain(), library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;A library&quot;)); } return commands.isEmpty()? null : new CompoundCommand(commands) ; } }
  • 227. Pre-Commit Listeners The TriggerListener class is convenient for processing notifications one by one, where appropriate class MyTriggerListener extends TriggerListener { MyListener() { // only interested in changes to Library objects super(NotificationFilter.createNotifierTypeFilter( EXTLibraryPackage.Literals.LIBRARY)); } protected Command trigger (TransactionalEditingDomain domain , Notification notification ) { Library library = (Library) next.getNotifier(); if (library.getName() == null) { return SetCommand.create(domain, library, EXTLibraryPackage.Literals.LIBRARY__NAME, &quot;A library&quot;); } return null; } }
  • 228. Transaction Validation When a read/write transaction commits, all of the changes that it performed are checked using the Validation Framework’s live validation capability If problems of error severity or worse are detected, then the transaction rolls back Pre-commit listeners can also force the transaction to roll back by throwing a RollbackException If a pre-commit listener cannot construct the command that it requires to maintain integrity, then it should roll back
  • 229. Transaction Nesting Both read-only and read-write transactions can nest to any depth Post-commit events are sent only when the root transaction commits Because even after a nested transaction has committed, it can be rolled back if its parent (or some ancestor) rolls back Pre-commit events are sent at every level of nesting Because a parent transaction may assume data integrity conditions guaranteed by triggers when it resumes Validation is performed on all changes when a root transaction commits Because triggers must be invoked first, in nested transactions
  • 230. Transaction Nesting Nested transactions inherit options from their parents The standard options cannot be disinherited. e.g., if a parent transaction does not send post-commit notifications, then none of its descendents will, either, even if they explicitly specify Boolean.FALSE for that option Nested transactions can, however, apply more options than their parents e.g., a child transaction can disable notifications. When its parent commits, the changes that it reports will simply exclude any that occurred during the execution of the child The inheritance of custom options in an extension of the transaction API is defined by that extension
  • 232. UI Utilities The Transaction API includes some utilities for building transactional editors Use the editing domain to create read-only and/or read-write transactions as necessary Substitute for the default EMF.Edit implementations
  • 233. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 234. Workbench Integration The WorkspaceEditingDomainFactory creates editing domains whose command stacks delegate undo/redo history to the Eclipse Workbench’s IOperationHistory
  • 235. Workbench Integration To use the operation-history-enabled editing domain with your editor, simply register it with the appropriate factory class The IWorkspaceCommandStack delegates to an operation history Using IUndoContext s, editors for different resources in the same editing domain can provide undo/redo menus that show only the changes affecting that editor <extension point=&quot; org.eclipse.emf.transaction.editingDomains &quot;> <editingDomain id=&quot;com.example.MyEditingDomain&quot; factory=&quot; org.eclipse.emf.workspace.WorkspaceEditingDomainFactory &quot;/> </extension>
  • 236. EMF Operations The command stack internally wraps EMF Command s in undoable operations and executes them on the operation history Clients can also construct Abstract- EMFOperation s and execute them on the history CompositeEMFOperation s can freely compose both EMF and non-EMF changes
  • 237. EMF Operations AbstractEMFOperation s execute themselves within a transaction on their editing domain Provides rollback support and automatic undo/redo just as the RecordingCommand does CompositeEMFOperation s can compose EMF operations and operations on other domains e.g., a composite can change objects in an EMF resource as well as edit parts in a GEF drawing surface and code in Java source files that are all interrelated Undo/redo is fully supported and preserves ordering dependencies between EMF and non-EMF changes Transaction rollback correctly undoes non-EMF changes
  • 238. EMF Operations IOperationHistory history = workbench.getOperationSupport() .getOperationHistory(); IUndoableOperation operation = new AbstractEMFOperation (domain, “ Create Books in Libraries”) { protected IStatus doExecute (IProgressMonitor monitor, Iadaptable info) throws ExecutionException { Iterator iter = resource.getAllContents(); while (iter.hasNext()) { // changes are determined on-the-fly Object next = iter.next(); if (next instanceof Library) { ((Library) next).getBooks().add( LibraryFactory.eINSTANCE.createBook()); } } return Status.OK_STATUS; }}; operation. addUndoContext (myEditorContext); history. execute (operation, new NullProgressMonitor(), null);
  • 239. Transaction Options As is the case with Command s, EMF operations can execute with transaction options A Map of options can be passed to the operation constructor. These are used during execution to initialize the transaction The AbstractEMFOperation::undo() and ::redo() methods use the following transaction options: OPTION_NO_UNDO : because we are undoing or redoing a previous recording, there is no need to record anew OPTION_NO_TRIGGERS : triggers performed during execution were recorded and are automatically undone; any additional changes would be inappropriate OPTION_NO_VALIDATION : there is no need to validate a reversion to a previous state of the data
  • 240. Resource Undo Context The editing domain for workbench integration automatically applies contexts to operations that are executed on its history For each resource affected by a transaction, a resource undo context is applied to the operation A resource is affected by any change to an object that it contains or by a change in another resource that adds a cross-reference to it An editor that uses a resource context as its editor context will populate its undo and redo menus with operations that affected its resource
  • 241. Undo/Redo Actions The workbench integration API provides replacements for EMF’s undo/redo actions that delegate to the operation history API’s action handlers These wrappers create undo/redo action handlers on the undo context obtained by adapting the active editor part to the IUndoContext type Usually this undo context is a ResourceUndoContext
  • 242. Agenda EMFT in a Nutshell Validating Models Querying Models Working with Transactions Working with the Operation History Summary
  • 243. Summary We have learned how to validate EMF resources on demand and on-the-fly using the EMFT Validation Framework search EMF resources using the EMFT Query Framework implement data integrity in EMF resources in a concurrent programming environment using the EMFT Transaction API integrate EMF-based editors with the Eclipse Workbench’s undo/redo framework using the EMFT Transaction API
  • 244. Resources EMF documentation in Eclipse help Overviews, tutorials, API reference EMF project Web site http://www.eclipse.org/modeling/emf/ Overviews, tutorials, newsgroup, Bugzilla Eclipse Modeling Framework by Frank Budinsky et al. Addison-Wesley; 1st edition (August 13, 2003) ISBN: 0131425420.
  • 245. Resources EMFT documentation in the Eclipse on-line help Overviews, tutorials, and API reference (Javadocs) EMFT components Web site Home page: http://www.eclipse.org/emft Newsgroup: news://news.eclipse.org/eclipse.technology.emft Bugzilla: https://bugs.eclipse.org/bugs/ Wiki: http://wiki.eclipse.org/EMFT
  • 246. Legal Notices IBM, Rational, WebSphere, Lotus, alphaWorks, and Rational Rose are registered trademarks of International Business Machines Corp. in the United States, other countries, or both. Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others.

Editor's Notes

  • #41: You will also need to: - manually change the JDK compliance level in the Java Compiler project properties or workspace preferences - Update the JRE container in the project’s classpath (use the Plug-in Manifest Editor: on the overview page, select “Update the classpath settings”)
  • #87: Inverse References - Finding the opposite of a unidirectional association
  • #88: Initially the arrows are proxies and when the references in Resource1 are resolved, they are replaced by the actual object from Resource2. The 2 nd proxy will be a proxy until it is accessed. When the 1 st proxy is resolved Resource2 is loaded into the ResourceSet but that doesn’t resolve all the proxies.
  • #89: The cross referencers check the containment tree of an EObject. Make it clear that a proxy is not “referenced” – this is a “transient” state.
  • #90: ECoreUtil.CrossReferencer is a convenient utility class for locating cross-references (that is, non-containment references) in the containment tree, or trees, rooted at a specified EMF object, resource, or resource set, or arbitrary collection of all three. The result of the search is stored in the cross-referencer’s base HashMap. Entries are keyed by reference targets, and their values are the collections of EStructuralFeature.Settings that identify all the source object-feature pairs referencing the keyed target. ECoreUtil.ExternalCrossReferencer is a convenient utility class for locating external cross-references in the containment tree, or trees, rooted at a specified EMF object, resource, or resource set, or arbitrary collection of all three. An external cross-reference is one that has a target that is not within the containment structure rooted at the object(s) being searched. ECoreUtil.ProxyCrossReferencer is a convenient utility class for locating proxies in the containment tree, or trees, rooted at a specified EMF object, resource, or resource set, or arbitrary collection of all three. ECoreUtil.UnresolvedProxyCrossReferencer is a convenient utility class for locating unresolvable (broken) proxies in the containment tree, or trees, rooted at a specified EMF object, resource, or resource set, or arbitrary collection of all three. ECoreUtil.UsageCrossReferencer is a convenient utility class for locating cross-references in the containment tree, or trees, rooted at a specified EMF object, resource, or resource set, or arbitrary collection of all three, with targets that are specific objects of interest. One or more objects of interest can be passed to the static find() or findAll() methods, respectively, which in turn construct an instance, with the search root(s), and then call their corresponding findUsage() or findAllUsage() instance methods.
  • #91: Is exposed on InternalEObject
  • #92: Explains why the name “CrossReferencer”. This is an informal qualification.
  • #94: As explained in the “Introduction to EMF” tutorial, the EObjectValidator is used as base of generated validators and directly for packages without additional constraints defined.
  • #96: Not always can we choose the “proxy handling” option we would like to…
  • #97: Formatted string: /, encoded, … Encoding is done by Converting the character string into a sequence of bytes using UTF-8 Convert each character that is not an ASCII letter or digit into %HH, where HH is the hexadecimal value of the byte URL: Resources that can be accessed with existing protocols URN: “Intended to serve as persistent, location-independent, resource identifiers” oasis urn: http://rfc3121.x42.com/
  • #99: URI.encodeFragment(String) can be used to produce a valid fragment.
  • #103: The default value of the “Resolve Proxies” attribute in an Ecore model is true.
  • #104: We could also call book.eContainer().eResource.getURI() instead of just library.eResource().getURI(), to illustrate that the book hasn&apos;t been removed from its container (although, that&apos;s kind of obvious from the fact that it ends up back in the same resource as the library)…
  • #105: Should also mention generated editor support for containment proxies (Control / Uncontrol menu items)…
  • #109: The question we want to answer is: what books were written by Dave? We could also use the UsageCrossReferencer…
  • #110: Why are we not defining what an ECrossReferenceAdapter is? Because we (should) know what a CrossReferencer and an Adapter are…
  • #111: The question we want to answer is: what books were written by Dave?
  • #113: This is not used by the generated UI to decided whether an editor is dirty or not - EMF.Edit monitors the state of the command stack of the EditingDomain…
  • #114: Resource.Internal, like InternalEObject and EStructuralFeature.Internal, is not really an “internal” API – it’s an API of less commonly used implementation oriented methods… all resources are assumed to implement this interface, and do so by virtue of extending ResourceImpl.
  • #119: Generates implementation classes without separate interface declarations Set the value of the ‘Suppress Interfaces’ generator model property to ‘true’
  • #121: Generates code without a package interface declaring metadata accessors and constants - these are generated into the package implementation, instead - Factory doesn’t extend EFactory Set the value of the ‘Suppress EMF Meta Data’ generator model property to ‘true’
  • #122: Generates code where interfaces for modeled root classes extend a specified interface, or nothing at all Clear or set the value of the ‘Root Extends Interface’ generator model property - Qualified name of interface, which need not extend EObject
  • #123: Generates code without @model tags in the Javadoc Set the value of the ‘Suppress EMF Model Tags’ generator model property to ‘true’
  • #124: Generates methods for features and operations which use standard Java collection and object types instead of those from EMF (e.g. EList, EMap, EObject) Set the value of the ‘Suppress EMF Types’ generator model property to ‘true’
  • #126: Header.javajetinc is an example of a template that should perhaps always be replaced – to contain your copyright.
  • #127: Dynamic “placeholder” template can also add required imports for compiling the template (in case the insertions reference new types). Need to reference default template “container” in JET project settings – i.e. templates;@/org.eclipse.emf.codegen.ecore/templates.
  • #128: Dynamic “placeholder” template can also add required imports for compiling the template (in case the overrides reference new types). Need to reference default template “container” in JET project settings – i.e. templates;@/org.eclipse.emf.codegen.ecore/templates.
  • #136: Of course, there is always a trade-off between time and space concerns…
  • #138: Of course, virtual feature delegation has a (significant) performance cost. We are also working on a VirtualEObjectImpl which will use virtual slots instead of a properties holder…
  • #141: OPTION_DEFER_IDREF_RESOLUTION Option value: Boolean This option can be enabled to defer resolving references within a resource until the whole document has been parsed. The default strategy is to try to resolve each reference as it is encountered and then, at the end, resolve any ones that failed. This wastes time looking up forward references that do not exist yet, which, if you&apos;re using intrinsic IDs, can involve iterating over every object in the resource. OPTION_USE_PARSER_POOL Option value: org.eclipse.emf.ecore.xmi.XMLParserPool We strongly encourage to set this option for EMF load operation. This option is used to provide a parser pool, from which SAXParser instances are created and reused. XMLParserPool defines a simple interface for obtaining and releasing parsers based on their features and properties. Specifying a parser pool, such as an instance of the default implementation, XMLParserPoolImpl, can improve performance dramatically when a resource performs repeated loads. A single parser pool can also be shared among multiple resources. Default implementation is also thread-safe. OPTION_USE_XML_NAME_TO_FEATURE_MAP Option value: java.util.Map This option can be used to share the cache of mappings between qualified XML names (namespace + local name) and corresponding Ecore features across invocations of load(), or even among resources. It can take some time to determine these associations, since they can be affected by ExtendedMetaData or an XMLMap, so they are cached during a load. If you use this option to specify the same map for several loads, that instance will be used as the cache, improving the performance for all but the first. You can share a single map among multiple resources, unless they load different models with conflicting qualified names.
  • #142: OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List Specify a list as a place holder for caching information during the subsequent saving of XML documents. This option can improve performance for serialization (saving) of multiple XML resources. This option is similar to the OPTION_USE_XML_NAME_TO_FEATURE_MAP which is used for deserialization (loading). OPTION_USE_DEPRECATED_METHODS Option value: Boolean Use methods that were deprecated in EMF. The default value is true. To improve deserialization performance turn this option to false. The methods affected are: XMLHelper#createObject(org.eclipse.emf.ecore.EFactory, EClassifier) XMLHander#handleNamespaceAttribs() XMLHandler#createObjectFromFactory(EFactory factory, String typeName) XMLLoadImpl#getEncoding() Note: if you use this option the SAX parser used for parsing documents must be namespace-aware parser, i.e. the namespaces should be turned on for the parser used. The default parser implementation is not namespace-aware. To turn on namespaces, either use OPTION_USE_PARSER_POOL or overwrite XMLLoadImpl#makeParser()
  • #143: OPTION_FLUSH_THRESHOLD Option value: Integer This option can be used to specify a maximum number of characters to allow in the output stream before flushing it. This reduces the memory used in serializing a large file, but it is slower than the default behavior. OPTION_USE_CACHED_LOOKUP_TABLE Option value: java.util.List This option provides a placeholder to cache information about structure of the model. (using qualified XML names as a key for caching information). When possible, the same placeholder list should be shared among resources, unless you intent to serialize instances of different models. OPTION_CONFIGURATION_CACHE Option value: Boolean This option can be enabled to cache and reuse generic data in repeated save operations, avoiding the cost of reinitializing the data. This option is save to use when serializing instances of the same model.
  • #144: OPTION_FORMATTED Option value: Boolean This option is used to disable formatting of documents, omitting whitespaces and line brakes, to improve the performance of saving and, subsequently, loading the resulting document. This means fewer bytes have to be written and read, but the serialization will be less human-readable. OPTION_USE_FILE_BUFFER Option value: Boolean This option can be enabled to accumulate output during serialization in a temporary file, rather than an in-memory buffer. This reduces the memory used in serializing a large file, but it is slower than the default behavior.
  • #146: Every solid box in this picture represents a way to describe a modeled domain.
  • #148: The HTML exporter even understands generics in models, highlighting things like type parameters
  • #149: When exporting a model as a schema, we would need the qualified name of the package if we were adding an Ecore package annotation.
  • #150: Before the Importer and Exporter hooks, we used to see all types of approaches to, for example, convert a proprietary format to Ecore: menu items, separate application, tool bar buttons, import wizard, …
  • #153: That’s all one needs to know to provide an importer or an exporter. The rest of this section will address the “non-mandatory” framework we’ve created to make it easier to write converters.
  • #155: Ideally, XML references would be based on identifiers, e.g. UUIDs.
  • #156: The Ecore2Ecore mapping editor is much like the XSD2Ecore mapping editor.
  • #157: The Ecore2XML editor is just a standard EMF-generated editor.
  • #161: These steps cab be done in a customized resource factory implementation to set the default load/save options for all resources managed by the factory…
  • #162: Could also be done by a customized editor or programmatically when calling the load()/save() methods.