The traditional approach of software development faces many challenges, like a paucity of technical skills, poor product quality, and maintainability. These challenges are further aggregated by limited availability of distinctive resources having domain and technical expertise.
According to a survey, the Standish Group Chaos Report 2009, only 32 percent of the total projects are delivered on time, on budget, and with required features and functions. The rest gets cancelled or their budgets are overshot. One of the main reasons for overshooting the budget and timeline is lack of systematic approach to software development that requires an increase in reusability, bringing the manufacturing process in software development. Software development is a labor intensive work that requires code written from scratch following a prescribed architecture, design patterns, and quality standard. Above all, in a typical development team, few have the required technical expertise and domain knowledge to execute the project. All these factors result in errors bugs in the product, shift of project deadline, more time to market, and overshooting of budget.To overcome the challenges raised due to the traditional approach of software solution development, we introduce the concept of a software factory.A software factory is a development approach that automates the software application artifacts generation, therefore enabling the organization to achieve higher levels of productivity by assembling reusable and well-defined components. It also enforces best practices, organizational constraints, customized framework, etc. This approach leverages the knowledge gained and assets produced during previous software application developments. This approach is analogous to an assembly line development mechanism where families of product are assembled together with augmentation of hand crafted customization. We will deal with software factories in this article. The concept of the software factory will be realized through the Model Driven Development (MDD) approach as both are laid upon the common foundation of platform independence and model driven. Eclipse Graphical Modeling Framework will be used to achieve the same. Some advanced features of GMF like custom images, tooling group, validations, etc will be covered in the article.As part of a software factory implementation, we will consider banking hierarchy system for better understanding and will generate a sample XML file from the model created by the user. In the real world, any type of artifact can be generated through software factories based on the requirements.What Is a Software Factory?
A software factory is an approach which automates the software development. Software applications generated are based on end user requirements gathered through an assembly process. This approach increases the reusability, and hence the completion time for software projects gets reduced. Knowledge and assets earned during previous software projects are utilized and only new components of code require traditional way of coding. It increases the level of abstraction by using modelling or visual assembly language. As MDA, software factories also follow model driven approach. In the following article, we will create a model file and then generate an XML file based on that model. In the real world, an XML file can be replaced by any other artefact e.g. java classes, configuration files, etc. Let’s start with a use case description.Usecase description
![](http://assets.devx.com/articlefigs/ACFC0.jpg)
![](http://assets.devx.com/articlefigs/ACFC2.jpg)
![](http://assets.devx.com/articlefigs/image006.jpg)
![](http://assets.devx.com/articlefigs/image008.jpg)
Step 1: Build a Domain Model
Define domain model file (ecore file) based on model described above. Hence, we will have a node Application as the first node of the metamodel. Application node will have Bank as an EReference child which will have its own set of attributes like name, etc. Bank will have collection of Branches (another EClass) and Branches will in turn have many Services. Generate EMF model from ECore file. Generated EMF model is then used to generate model and edit code. Right click on genmodel file to generate the same.Step 2: Customize Graphical Definition
Launch the Simple Graphical Definition Model wizard and load the ecore file just created. Select Branch, Bank and Service as node; branchRelation and serviceRelation as links; and name of each node (except Application) as attribute.![](http://assets.devx.com/articlefigs/image010.jpg)
- i. Delete all children of Figure Descriptor Bank present under Figure Gallery and create a new child of type Custom Figure.ii. Given it a name BankFigure and Qualified Class Name as org.eclipse.gmf.runtime.draw2d.ui.render.figures.ScalableImageFigureiii. Do the same for Figure Descriptors Branch and Service. Give the name of Custom Figure according to the Figure Descriptor name.iv. Now we have to create external labels for all the nodes. Create a new Figure Descriptor BankLabelFigure. Create a child of type Label and give it a name BankLabelFigure. Text property is there to show some default text as label value. Create a child under Figure Descriptor of type childAccess and set its Figure property to BankLabelFigure.v. Create the labels for Branch and Service in the same way.vi. We will now modify Diagram Labels so that they point to external labels which we have just created. Click on Diagram Label BankName and set its Figure property to Figure Descriptor BankLabelFigure. This will automatically change the external property to true.vii. Modify other Diagram Labels in the same way.
This ends our modification to gmfgraph file.
Step 3: Palette Customization
Create tool definition by launching Simple Tooling Definition Model wizard. Select all nodes and connections for palette.![](http://assets.devx.com/articlefigs/image012.jpg)
- i. Create a Tool Group under Palette and name it as Nodes. Move all nodes – Bank, Branch and Service under it.ii. Create a Tool Group called Connections and move all connection tools under it. Rename bankBranchRelation as Bank’Branch to give it a more meaningful name. Do the same for branchServiceRelation.
Step 4: Modify Mapping File
This step describes the creation of mapping file. Launch Guide Mapping Model Creation wizard to create the gmfmap file. Select Bank, Branch & Service as nodes and bankBranchRelation & branchServiceRelation as links. After generation of mapping file, cross check all the mappings as sometimes wizard creates erroneous mappings.![](http://assets.devx.com/articlefigs/image014.jpg)
Adding validations
Validations are added to avoid user from making mistakes while creating diagram and to provide some constraints. GMF supports OCL for validations. OCL is a rule based language and expressions are used to add constraints. For e.g. name.size()>0 (this implies that name should not be null).![](http://assets.devx.com/articlefigs/image016.jpg)
- i. Add a child ‘Audit Container’ under Mapping node. Give its name, Id and description. All rules will be added under this.ii. For each constraint, an Audit Rule is added. To put a constraint for uniqueness of the name of a node, name->isUnique(property) constraint is added. So we will add uniqueness check for name of the Bank because two banks cannot have same names. Create an Audit Rule under Audit Container and give it a name – bankNameUniqueViolation. Message property value will be shown as error message when the rule is violated. Add a Constraint under Audit Rule and put following constraint under body banks->isUnique(name)Add Domain Element Target under Audit Rule and point it to Application. This means that in Application, bank name should be unique.iii. We will add one more type of validation which is the check for null names. It is mandatory for nodes to have name. To achieve this, create an Audit Rule ‘bankNameNullValidation’ and add Constraint with body value as name.size() > 0 and Domain Element Target as Bank. This means that property name in bank should have size greater than zero means it should have some value.iv. Follow the same steps for checking null for name of Branch and Service.
Step 5: Generator Model
After mapping file is created, create generator model by right clicking the gmfmap file and selecting option ‘Create Generator Model’. We will customize this file little bit for enabling validations and for managing the diagram file.- i. Select the Gen Editor Generator node, set the following properties:
- a. Same File for Diagram and Model : true b. Diagram File Extension : modelc. Domain File Extension : model
These settings will create a single file for diagram editor and with model extension. If you want two files, set it to false and you can also change the extension of the diagram file by setting a different value.ii. Select Gen Diagram node under Gen Editor Generator node and set the following properties :
- a. Validation Decorators : trueb. Validation Enabled : true
This enables the validation. Without setting it to true, rules added under Audit Container will not be enabled.
Step 6: Alter Diagram Code
Right click the generator model and generate the diagram code. There will be some errors in the generated code as we have referred ScalableImageFigure class for custom figure which is not available to the project. We need to add plugin for that class to remove the error.- i. Open plugin.xml of project with diagram extension (one which is generated above) and add org.eclipse.gmf.runtime.draw2d.ui.render to required plug-ins under dependencies tab.ii. We have to modify a method to show custom images on our diagram editor. Open BankEditPart.java and copy the following code in createNodeShape() method.
URL url = FileLocator.find(ModelDiagramEditorPlugin.getInstance().getBundle(), new Path("icons/bank.jpg"), null);return new ScalableImageFigure(RenderedImageFactory.getInstance(url) ,true, true, true);
Change the annotation of the method from @generated to @NOT generated. This does not overwrite the method if diagram code is generated again. Do the same for BranchEditPart.java and ServiceEditPart.java. Copy the images you have selected for Bank, Branch and Service under icons directory in diagram project. If you want to change the position of the label with respect to node then modify addBorderItem() method in the same class. Label offset can also be managed in the same method. By default, label is positioned to the south of node and offset is 20. Remember to change the annotation to NOT generated otherwise method will be overwritten. Invoking validation while saving diagram fileBy default, diagram file can be validated by selecting Validate under Diagram menu. This adds an extra task for the user to validate the file which sometimes can be skipped from mind of the user easily. To avoid this, we will validate the model diagram while saving the file. Follow the steps to accomplish this:
- i. There is a method doSaveDocument() in ModelDocumentProvider class which is responsible for saving the diagram model. We will call validation from this method. Add following line:ValidateAction.runValidation((View) document.getContent()); as first line of the method. This will invoke validation as soon as file is saved.If you want to add some more functionality while saving, then this is the place to do it.ii. Change the annotation to @NOT generated.
Method doSaveDocument() is called when diagram is saved. Adding it as first line will invoke validations while saving it. Till now we have done all the modifications for creating model on diagram editor. Now we will write code for generating XML file from model.
Step 7: Generate XML from model
The main objective of this article is to automate software development. We will generate an XML file from the diagram editor file which will be created by user. In real world, any type of file (java,xml,text,etc.) can be generated through this. We will add a menu item which will appear when model file is right clicked. That menu item will be linked to an action class. A wizard in which user would be asked the destination path for generating XML will come up on selecting the menu item. Follow the steps to achieve the same:- i. Define Extension point: Menu item is added by adding extension point. Refer to figure 9.
![](http://assets.devx.com/articlefigs/image018.jpg)
This piece of code is added in plugin.xml of main project. Define an action class for the extension point. We have BankAction class as the action class. This class would be responsible for opening a wizard which capture the destination information.An XML file will be generated at the captured destination path based on the model created by user on diagram editor. For model, we need to read the selected diagram editor file.Each active workbench window has the selection service which helps in tracking the current selection. Refer to the code snippet below.
ISelection selection = BankPlugin.getDefault().getWorkbench() .getActiveWorkbenchWindow().getSelectionService() .getSelection();
Create a wizard: Create a wizard which would be responsible for holding the destination path (refer to figure 10). ii. Figure 10: Wizard for capturing destination path.Override performFinish() method to add the logic for XML generation.
IStructuredSelection structured = (IStructuredSelection) selection;Object object = structured.getFirstElement();if (object instanceof IFile) { IFile file = (IFile) object; IPath resourcePath = file.getFullPath();TransactionalEditingDomain editingDomain = DiagramEditingDomainFactory .getInstance().createEditingDomain(); editingDomain.setID("org.eclipse.gmf.runtime.emf.core.editingDomain"); ResourceSet resourceSet = editingDomain.getResourceSet(); Resource modelResource = resourceSet.getResource(URI.createPlatformResourceURI(resourcePath.toString(), true), true);Application application = (Application) modelResource.getContents() .get(0); XMLGenerator.generate(application, bean.getPath());}
In the code snippet shown above, application variable holds the complete model object. This model object can be utilized to generate any type of file. Complete model object and destination path is passed to method generate of XMLGenerator class. iii. Generation: XML file is generated by using StringBuffer and IO. Refer XMLGenerator.java. Apart from using plain IO, freemarker templates, JET (Java Emitter Templates ), etc can be used to generate it. Not only XML, but any type of artefact can be generated using this approach.