An Object Oriented Model Transformer Framework ... - Semantic Scholar

0 downloads 0 Views 413KB Size Report
02] [Gogolla 02] [Kovse 02] [Kulkarni 02] [QVTPartners 03] [Schmidt 02] [Sendall 03]. [Ziadi 02]. Mercator ..... [Kulkarni 02]. V Kulkarni, R Venkatesh, S Reddy.
An Object Oriented Model Transformer Framework based on Stereotypes Weerasak Witthawaskul, Ralph Johnson Software Architecture Group Department of Computer Science University of Illinois at Urbana-Champaign Urbana, IL 61801 [email protected], [email protected]

Abstract MDA modelers, like programmers in general, will develop and reuse libraries. Some of these libraries will hide details of the platforms, so the mapping from a PIM to a PSM will have to transform libraries as well. Some libraries provide common object services while others provide domain specific functionalities. These libraries will not just be class libraries, but also profiles containing stereotypes. Mercator is an extensible tool for transforming a PIM that uses platform independent libraries to a PSM. It allows model compiler developers to specify stereotype-based transformation both for transforming new libraries and for transforming libraries to new platforms. Using the Mercator framework and platform independent libraries, it becomes possible to extend the tool to migrate from one technology to another by creating new mappings for the new technology and reusing the same PIM.

Introduction There are three main problems that must be solved to make MDA [MDA 01] modeling and transformation practical; 1) a precise, interchangeable platform independent and specific model specification, 2) platform independent libraries that can be used by PIM so that basic object or domain specific functionalities can be used and mapped into PSMs and 3) a transformation framework that allows model compiler developers to create new mappings to provide specialized implementations or support new target platforms. The first problem is addressed by the OMG UML 2.0 standard specification [UML2] and the release of a reference implementation from the Eclipse UML2 project [EclipseUML2]. It becomes possible to define interchangeable models that can be created and then manipulated by different tools and to extend UML models using the UML extension mechanism. The second problem is important because MDA will never be a success if model designers must build everything from scratch. Model builders will want to reuse both platform independent libraries such as models of insurance or banking and libraries that hide platform dependencies such as object persistence, object distribution, transaction, messaging, and security. These will be separate libraries defined by UML profiles that can be imported, used and transformed. The third problem is an active research area. There are many research projects that provide fundamentals for model transformation [Agrawal 02] [Appukuttan 03] [Miguel 02] [Gogolla 02] [Kovse 02] [Kulkarni 02] [QVTPartners 03] [Schmidt 02] [Sendall 03] [Ziadi 02]. Mercator [Witthawaskul 03] is one of them. It is based on object-oriented, extensible, stereotype-based model transformation that supports pluggable library transformation. Mercator separates two kinds of developers. The obvious kind is model designers who are responsible for designing and developing models that solve particular problems. They design solution models, import and apply platform independent model libraries and do not worry about how the platform independent models (PIMs) are mapped into the platform specific models (PSMs) until at a later stage. This group is considered ‘end users’ to the model transformation. The other kind is model compiler developers who are responsible for

defining platform independent libraries and providing the mappings between PIM and PSM. Mercator is designed for the latter group and provides ways to support platform independent libraries and their mappings into the tool. One company may reuse a domain specific PIM and generate customized implementations for their needs by developing their own library transformers. Another company may buy new library transformers to migrate their system from one technology to another as long as the system uses the same standard platform independent libraries.

Platform Independent Libraries One of the main causes of software evolution is changes in execution environment, middleware, protocol or infrastructure. An e-commerce system that migrates its object persistence technology from one technology to another, for example, from Enterprise JavaBeans [Sha 00] to Hibernate [Hib 03] (or vice versa), requires substantial changes in source code and deployment configurations. It’s difficult to understand the domain model and extract the actual business logic inside the model because the domain logic is often hidden among many implementation-specific details. A PIM should not contain these details. Instead, common services such as object persistence, distribution, transaction, messaging and security should be well defined and used by importing from platform independent libraries. To specify object persistence, for example, modelers import the object persistence library, specify which classes need to be persisted, attribute or compound attributes used for object identity and the APIs to store, load and find objects from persistence storage. Library transformers will be responsible for mappings these libraries into specific implementations and are selected during the model transformation. For example, object persistence library may contain transformers for an EJB Container Managed Persistence (CMP) transformer and Hibernate among others. Which transformer is used depends on the mapping method selection. In addition to separate common object functionalities into libraries, it should be simple to provide new mappings of existing libraries and to define new libraries. Model developers from different industries may want to use standard business models and tailor them to fit their domain specific needs. They may want to implement common object services differently. To do so, they develop their own transformers and describe how and where these transformers are executed. Common platform independent libraries are important in two ways. First, model designers use them in PIMs to solve their business problems without knowing details about how their models and libraries are mapped into the target platform. Modelers decide on mapping choices and provide extra information during the PIM-to-PSM transformation. These choices and extra information are stored in an annotation model thus separating PIM from implementation details and making the same PIM transformable into different platforms. Second, model compiler developers use platform independent libraries as contracts to implement new mappings that are more specialized or support new target technology/platform. However, providing platform independent libraries are not simple. Many libraries are dependent to one another. Some libraries require others, for example, object persistence library requires object identity library to provide object key while object distribution library uses object serialization to transport objects. Often times, the implementation choices may conflict with others. For example, object distribution cannot transport objects that serialize into a relational database. One implementation choice may constraint another, for example, Hibernate always store objects in relational table data source. Therefore choosing a file data source with Hibernate is not valid. This makes it hard to design libraries that are reusable and support dependency management.

2

Another potential problem in using high level, platform independent APIs is that it may take a lowest common denominator approach and not be as comprehensive as platform specific APIs. It is also hard to provide APIs that can be mapped into many different implementations. However, this is always a case for a higher level of abstraction such as a virtual machine. As long as the virtual machine is ported into a different operating environment, programs that run on the virtual machine can use virtual machine APIs without knowledge of the actual runtime environment. If the platform independent APIs are well defined, it is a matter of providing the mappings of these APIs into a new runtime platform and reusing the same PIM to generate different implementations running on different technology, middleware or platform. The mapping of platform independent models and libraries is an important part of a model transformation.

Model Transformation A model transformation is similar to a compiler. A traditional compiler parses textual source files and builds abstract syntax tree (AST) representation of the input sources. After the parsing, the compiler traverses the AST to create intermediate representations potentially in several passes. Each pass contains more concrete intermediate representation and optimization. The final result is an executable under a target machine. Similarly, a MDA model transformer parses an input PIM from a textual representation format in XMI into a model tree. The transformer traverses the input model tree and generates a more concrete output model. It can be processed in many passes. Each pass the transformer obtains extra information about the transformation either from the mapping algorithm or from the end user. The result of the model transformation is a PSM that can then be directly generated into source files. Unlike the compiler, however, mapping algorithms may be different depending on the target technology/infrastructure. For example, PIMs that use object distribution library are mapped differently if the target technology is XML/SOAP than if it is CORBA [Cor 02] or Java RMI [Java 00]. Changes in technology/infrastructure should not impact the PIM. Only new mappings are required. Thus transformation development can be done separately as needed. The Mercator framework provides a standard way to support platform independent libraries and to define new transformers for each library by using UML profiles. Modelers import different library profiles to use different library functionalities in their models. For example, to indicate that objects from a Car hierarchy are persistable, we import the Persistence profile and assign «Persistence::persistence» to the root of the Car class hierarchy. All instances of the Car class and its subclasses in the hierarchy will inherit the persistable capability. Additional persistence-related APIs are automatically introduced in persistable classes, for example, store(), load(), remove(), findById() and findAll(). These are platform independent and they hide the details how the object are actually stored and retrieved from a data store. Model compiler developers create transformers for mapping these APIs into different persistence methods. When the model transformation visits the model elements that contain the stereotype, it will choose a corresponding transformer that matches with the persistence method selected by the model developers. New platform can be supported by creating a PSM library transformer that translates platform independent APIs into the new target platform.

Stereotype-based Model Transformation Framework Mercator uses stereotypes to control the transformation. It stores transformers for each stereotype in the transformation registry. A stereotype may have more than one transformer if there is more than one way to transform the stereotype. There are two kinds of transformers: a node transformer and a tree transformer. A node transformer takes an input model element, validates the input and produces an output model element. A tree transformer takes an input model tree, iterates nodes in the input model tree in preorder, obtains stereotypes for each

3

node and looks up node transformers from the registry and invokes these transformers’ transform() methods with the current visiting node as the parameter. If the node element does not contain a registered stereotype, it will be passed unchanged to the output model. A node element may contain more than one stereotype, for example, a class that is persistable and distributable. Mercator will invoke corresponding transformers in a FCFS order. Even though this is currently not a problem, the order may become an issue if stereotypes are dependent and their transformers require specific order of execution. After all nodes are visited and no transformation error occurs, the output model tree will be given another stereotype so that the transformation algorithm will be applied again with the next tree transformer of the new stereotype. For example, the PIM-to-intermediate-PIM tree transformer takes a «PIM» input model, creates an output model and assigns the «MPIM» to the output so that Mercator will look up the intermediate-PIM-to-PSM transformer matching the «MPIM» from the registry and invoke it during the next transformation iteration. The transformation process will stop when the output model tree is no longer stereotyped which is usually a case after the PSM transformer generates source code from the PSM. A transformer validates the input model element subtree to makes sure that the input element and its children meet a set of constraints, for example, a persisted class (class that is stereotyped with «Persistence::persistence») must contain an attribute that is stereotyped with «Persistence::id». Mercator provides basic validators such as type validator, owned element’s stereotype checking, naming rules and allows model compiler developers to define new ones. The transformer may store or consult additional information from an annotation data structure. This data structure stores transformation related parameters and lives over the entire transformation process. It can also be stored and used in subsequent transformation. If the required information does not exist in the annotation, the node transformer will generate an error, thus preventing the tree transformer to proceed. The model designer will check the error, specify the required information and rerun the transformation tool again. Mercator performs model transformation in 3 passes using different transformers: 1) PIMTransformer that traverses a PIM, invokes platform independent stereotyped node transformers and generates an intermediate PIM, 2) MPIMTransformer that transforms UML model elements in the intermediate PIM into Java elements in a PSM, maps UML primitive types into Java types and invokes platform specific stereotyped node transformers to generate the output PSM. This output is a horizontal refinement of the input model with the expanded semantics of the applied stereotypes. 3) PSMTransformer that generates Java source code. Model compiler developers extend the Mercator tool by creating node transformers for platform independent libraries and register them into the transformation registry. Each library stereotype contains at least 2 transformers; one for PIM-to-MPIM and the other for MPIM-toPSM. These transformers will be invoked when the tree transformer visits the model elements that use the library stereotypes. During the model transformation, model designers may have to specify extra information. For example, there are many supported object persistence methods. The model designers have to choose a persistence method, data source type and an object identity type. Choices in persistence method may be among EJB, Hibernate, JDO, and XML etc. Data source type may be database, network streams or files. Object identity can be implemented in many ways (see [Fowler 03] for Identity Field). The choices and extra information associated with each choice are stored separately in an annotation model. To illustrate an example, suppose an input class model uses object persistence library. During the first pass, the PIMTransformer iterates over the input class model. If it finds UML elements without stereotype, it will copy them into the output model unchanged. If it finds a class element with «Persistence::persistence», it will obtain and invoke a PIM-to-MPIM

4

persistence transformer from the registry. The persistence transformer validates the class element. One of the validation rules is to check whether the class or its superclasses contains an identity attribute with «Persistence::id». The persistence transformer will allow persistable classes without identity attributes if the autogen_id flag in the annotation is true. In this case, it will automatically create an identity field for each class. If there is no identity field and autogen_id is false, it will throw an exception. This exception will be collected by the PIMTransformer and prevents the transformer to complete the pass. The model developers must fix the error and rerun the transformer until all transformers complete successfully. If the persistable class contains an identity attribute and other validation rules succeed, it copies the class’ attributes and adds persistence-supported operations (store, load, find) into the class element in the output MPIM. Next it stores information about object graph (objects reachable from the instance of the persistable class) into the annotation. This information will be used in the next pass for generating a model-scoped configuration information. At the end of the first pass, the PIMTransformer assigns «MPIM» to the output model. The second pass uses MPIMTransformer to iterate over the MPIM model. The transformer maps UML elements into Java elements in the output PSM. There is more than one way to map the persistable class elements. The model developers must choose a persistence mapping choice or accept the default choice. A persistable class with an EJB choice will activate the MPIM-to-PSM EJBPersistenceTransformer while a class with a Hibernate choice will activate the MPIM-to-PSM HibernatePersistenceTransformer. Each transformer will use information in the annotation from the previous pass to create an EJB deployment and Container Managed Relationship (CMR) files (in EJB case) or Hibernate configuration and mapping files (in Hibernate case). Each transformer will create implementation specific Java code into the body of each persistence-supported operation using parameterized code patterns. It also creates/uses helper classes (home, key, local/remote interfaces in EJB; configuration, session factory, session in Hibernate). Therefore one input element in the PIM may become n output elements in the PSM. At the end of this pass, the persistence related stereotypes are removed from the output PSM so that the persistence transformer will not be invoked in the third pass. The MPIMTransformer also assigns «PSM» to the output model. The third PSM-to-Code pass is a straightforward Java model-to-source code generation using the PSMTransformer. The output source code and the platform specific files from the second pass will be used and deployed in the target environment. If the model designer wants to change the persistence method from EJB to Hibernate, only the new mapping choice and a Hibernate-specific annotation need to be changed. The designer chooses the Hibernate mapping method, specifies Hibernate-related information in the annotation and reruns the transformation tool with the same PIM and receives a new output based on Hibernate.

Transformer Development Use Cases There are two primary use cases for model compiler developers. The first is to develop a new library profile. The goal of Mercator is to define commonly used platform independent object libraries. However, there may be a need for new libraries for use in specialized problem domains. For example, a B2B parts order profile for automobile supply chain system may require a specialized specification of parts and inventory. Model compiler developers define a set of related stereotypes in a library profile. Each stereotype contains properties and a specification of platform independent APIs. These APIs are contracts that can be used in a PIM and that each transformer must implement. Each stereotype also contains at least one transformer each for a PIM-to-MPIM and MPIM-to-PSM transformation and provides a way to add new transformers to generate different implementations. A library profile should contain test suites that can be tested during new mapping development.

5

The second and probably more common use case is to implement mappings of an existing platform independent library profile into a new implementation. For instance, model compiler developers may want to map object distribution using specialized object transport method instead of the provided Java-RMI or SOAP/XML. They will reuse the Object Distribution profile and create new mappings that generate different implementation from the defined platform independent APIs. For each defined stereotype, developer implements the required validator and transformer’s methods. The developer may choose to extend from AbstractModelTransformer for transformation that require an entire model tree traversal or extend from AbstractTransformer for transformation that occurs only at the stereotyped model element. For validation, the developer can choose among available validators or develop a custom validator by implementing from the IValidator interface. Next the developer registers the transformers into the Mercator transformer registry. Each entry contains the stereotype name, the based model it is applicable to (PIM, MPIM or PSM), a set of transformer class names and the default transformer name. Finally, developer runs the test suites defined in the library profile against new mappings to ensure that the result of the transformation works as expected. The Mercator tool prototype supports basic UML-to-Java transformation and object persistence mappings into Hibernate, EJB CMP 2.1 and custom XML based on XStream [XStream]. Figure 1 below shows an example of a Player with «persistence» gets transformed from a PIM to a Java PSM. Figure 2 shows the generated code block of the Hibernate implementation of the findByPrimaryKey() method.

Figure 1 A persistence Player class is mapped from a PIM into a Java PSM

Figure 2 A Hibernate generated code of the findByPrimaryKey() method in the Player class

6

We have defined other platform independent libraries and are developing their mappings. Possible future work includes comprehensive UML-to-Java and other library specifications and mappings, and other programming language support.

Summary This paper contributes in two aspects. First, it advocates the importance of platform independent libraries that specifies a set of stereotypes and a set of platform independent APIs. Model designers import library profiles and use them in the PIMs while the model compiler developers create transformers for each stereotype and implement mappings for each APIs. PIM does not contain implementation specific details. Parameterized transformation data is stored in an annotation and can be reused. Second, it describes the Mercator object-oriented, stereotype-based model transformation framework. The tool provides basic model element validation, traversal, UML-to-Java mappings and supports pluggable transformers. These transformers can be developed to generate more efficient code and/or to support new target platforms. Thus, it becomes possible to use the tool to migrate from one technology to another by creating new mappings for the new technology and reusing the same PIM. There are many works in the model transformation area. Czarnecki classified and compared approaches in model transformations [Czarnecki 03]. We believe that object oriented transformation framework is one of the practical methods to support evolving software systems. Model compiler developers use Java to develop custom transformers from contracts described in platform independent libraries. Changes in technology/platform will only require obtaining new transformers from vendors or developing their own transformers. Separating common object functionalities into platform independent libraries will result in a more reusability and applicability of the domain specific object models. Works from [EDOC 02] [Silaghi 03] [Simmonds 03] [Almeida 03] emphasized on platform independent modeling but they have yet grouped common services into pluggable transformation service libraries or provided platform independent APIs.

References [Agrawal 02]

[Almeida 03] [Appukuttan 03]

[Caplat 02]

[Czarnecki 03]

[Cor 02] [EclipseUML2] [EDOC 02]

A Agrawal, T Levendovszky, J Sprinkle, F Shi and G Karsai. “Generative Programming via Graph Transformations in the ModelDriven Architecture”. In OOPSLA 2002 Workshop in Generative Techniques in the context of Model Driven Architecture. 2002. J P Almeida, et. al., “A system approach to platform-independent design based on the service concept”, In EDOC 2003. B Appukuttan, et al. “A model driven approach to building implementable model transformations”. In Workshop in Software Model Engineering, Sixth International Conference on the Unified Modeling Language, 2003. G Caplat , J Sourrouille. “Model Mapping in MDA”. In Workshop in Software Model Engineering, Fifth International Conference on the Unified Modeling Language, 2002. K Czarnecki and S Helson. “Classification of Model Transformation Approaches”. In OOPSLA 2003 Workshop in Generative Techniques in the context of Model Driven Architecture. 2003. Common Object Request Broker Architecture Specification, Object Management Group, 2002. The Eclipse UML2 project, http://eclipse.org/uml2. UML Profile for Enterprise Distributed Object Computing Specification, Object Management Group, 2002.

7

[Fowler 03] [Gogolla 02]

[Hib 03] [Sha00] [Java 00] [Kovse 02]

[Kulkarni 02] [MDA 01] [Miguel 02]

[QVTPartners 03] [Schmidt 02]

[Sendall 03]

[Sha 00] [Silaghi 03]

[Simmonds 03]

[UML2] [Witthawaskul 03]

[XStream] [Ziadi 02]

M Fowler, Patterns of Enterprise Application Architecture, AddisonWesley, 2003. M Gogolla, A Lindo, M Richters, P Ziemann. “Metamodel Transformation of Data Models”. In Workshop in Software Model Engineering, Fifth International Conference on the Unified Modeling Language, 2002. Hibernate2 Reference Documentation. http://hibernate.bluemars.net. Java 2 Platform, Enterprise Edition: Platform and Component Specifications, 2000. B Joy, G Steele, J Gosling, G Bracha. The Java Language Specification. Addison-Wesley, 2000. J Kovse, T Härder. “Generic XMI-Based UML Model Transformations”, in: Proc. 8th Int. Conf. on Object-Oriented Information Systems (OOIS'02). V Kulkarni, R Venkatesh, S Reddy. “Generating Enterprise Applications from Models”. In OOIS-MDSD Workshop 2002. Model Driven Architecture, ormsc/2001-07-01. M Miguel, et al. “Specifications of Model Transformations Based on Meta-Templates”. In Workshop in Software Model Engineering, Fifth International Conference on the Unified Modeling Language, 2002. DSTC, IBM and CBOP. “MOF Query / Views / Transformations, First Revised Submissions”. Aug 18, 2003. D Schmidt, et al. “CoSMIC: An MDA Generative Tool for Distributed Real-time and Embedded Component Middleware and Applications”. In OOPSLA 2002 Workshop in Generative Techniques in the context of Model Driven Architecture. 2002. S Sendall, “Combining Generative and Graph Transformation Techniques for Model Transformation: An Effective Alliance?”. Submitted to the OOPSLA 2003 Generative techniques in the conext of MDA Workshop. Java 2 Platform, Enterprise Edition: Platform and Component Specifications, 2000. R Silaghi. “Better Generative Programming with Generic Aspects”. In OOPSLA 2003 Workshop in Generative Techniques in the context of Model Driven Architecture. 2003. D Simmonds, S Ghosh, R France. “An Aspect Oriented Model Driven Architectural Framework for Middleware Transparency”. In Proc. Of the Early Aspects Workshop at AOSD 2003. August 2003. http://www.uml.org W Witthawaskul, “Specifying Persistence in Platform Independent Models”. In Workshop in Software Model Engineering, Sixth International Conference on the Unified Modeling Language, 2003. http://xstream.codehaus.org/ T Ziadi, B Traverson, J Jezequel, “From a UML Platform Independent Component Model to Platform Specific Component Models”. In Workshop in Software Model Engineering, Fifth International Conference on the Unified Modeling Language, 2002.

8

Suggest Documents