Sep 18, 2007

Model Driven Software Development with openArchitectureWare

MDSD and code generation is an interesting topic for a couple a years now.
As Microsoft is pursuing an Visual Studio integrated approach with DSL (domain specific languages) and Software Factories (like the Web Client, Web Service, etc.) there are other approaches following the UML and the OMG more closely.
Yesterday I had the chance to join an interesting session with Ueli Brawand generating C# code with the Java MDA/MDD code generation framework openArchitectureWare.
In a tutorial we were first creating a static class model with EA (Sparx Enterprise Architect). oAW is an Eclipse add-in and I was creating a workflow in a special ANT/MSBUILD/MAKEFILE related language:

<?xml version="1.0" encoding="UTF-8"?>

<workflow>

 

    <bean class="oaw.uml2.Setup" standardUML2Setup="true" />

 

    <component class="oaw.uml2.toolsupport.ea.EA_Xmi2Exporter" >

        <EapFile value="Model/MDSD.eap" />

        <PackageName value="Models/Project Model/MDSD.Tutorial" />

        <ModelFile value="" />

        <OutputSlot value="model" />

 

        <Profile value="Profile/oa.profile.uml" />

        <StereotypeProfile name="root" value="oa" />

        <Cleanup value="true"/>

    </component>

 

    <component class="oaw.emf.XmiReader">

        <modelFile value="tutorial.uml" />

        <outputSlot value="model"/>

    </component>

 

    <component class="oaw.check.CheckComponent">

        <metaModel id="EmfMM" class="oaw.type.emf.EmfMetaModel">

            <metaModelPackage value="org.eclipse.emf.ecore.EcorePackage"/>

        </metaModel>

        <metaModel id="UmlMM" class="oaw.uml2.UML2MetaModel"/>

        <metaModel id="oaMM" class="oaw.uml2.profile.ProfileMetaModel">

            <profile value="Profile/oa.profile.uml" />

        </metaModel>

 

        <checkFile value="check::MyCheck" />

        <expression value="model.eAllContents" />

    </component>

 

    <component id="dirCleaner"

          class="oaw.workflow.common.DirectoryCleaner"

        directories="src-gen"/>

 

    <component id="generator" class="oaw.xpand2.Generator" skipOnErrors="true">

        <fileEncoding value="ISO-8859-1" />

 

        <metaModel id="EmfMM" class="oaw.type.emf.EmfMetaModel">

            <metaModelPackage value="org.eclipse.emf.ecore.EcorePackage"/>

        </metaModel>

        <metaModel id="UmlMM" class="oaw.uml2.UML2MetaModel"/>

        <metaModel id="oaMM" class="oaw.uml2.profile.ProfileMetaModel">

            <profile value="Profile/oa.profile.uml" />

        </metaModel>

 

        <expand value="xpand::Root::Root FOR model"/>

 

        <outlet path="src-gen/">

            <!--postprocessor class="oaw.xpand2.output.JavaBeautifier"/-->

            <postprocessor class="oaw.xpand2.output.XmlBeautifier"/>

        </outlet>

 

    </component>

 

</workflow>


We wanted to generate code for ORM (OpenAccess) business object classes. Therefore we wrote an .xpt file defining the code generation process:

«EXTENSION oaw::uml2::support::UMLSupport»

 

«DEFINE Root FOR uml::Model»

«EXPAND OA_Gen FOREACH ownedElement»

«ENDDEFINE»

 

«DEFINE OA_Gen FOR uml::Package»

«EXPAND OA_Gen FOREACH ownedElement»

«ENDDEFINE»

 

«DEFINE OA_Gen FOR oa::BusinessObject»

«FILE name+".cs"»

using System;

using System.Collections.Generic;

using System.Text;

 

namespace BusinessObjects

{

    [OpenAccess.Persistent()]

    public class «name»

    {

«EXPAND OA_Gen_Attribute FOREACH ownedAttribute»

«EXPAND OA_Gen_Property FOREACH ownedAttribute»

    }

}

«ENDFILE»

«ENDDEFINE»

 

«DEFINE OA_Gen_Attribute FOR uml::Property-»

        private «type.name» «name»;

«ENDDEFINE»

 

«DEFINE OA_Gen_Property FOR uml::Property»

        public «type.name» «name.toFirstUpper()»

        {

            get { return «name»; }

            set { «name» = value; }

        }

«ENDDEFINE»

 

«DEFINE Root FOR uml::Element»«ENDDEFINE»

«DEFINE OA_Gen FOR uml::Element»«ENDDEFINE»

«DEFINE OA_Gen_Attribute FOR uml::Element»«ENDDEFINE»

«DEFINE OA_Gen_Property FOR uml::Element»«ENDDEFINE»


Resulting in the following .cs file:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace BusinessObjects

{

    [OpenAccess.Persistent()]

    public class Order

    {

        private DateTime shippingDate;

        private string customer;

        private OrderItem orderItems;

 

 

        public DateTime ShippingDate

        {

            get { return shippingDate; }

            set { shippingDate = value; }

        }

 

        public string Customer

        {

            get { return customer; }

            set { customer = value; }

        }

 

        public OrderItem OrderItems

        {

            get { return orderItems; }

            set { orderItems = value; }

        }

 

    }

}



In my opinion oAW makes sense:
- for (bigger) "Product Line Architecture" - like projects
- to generated entity/business object/data layer code (20 and more BOs)
- only for parts of an application
- to come around shortcomings of EA concerning code generation