How to use oAW with a JavaBeans based Meta Model
openArchitectureWare can process any model. One common use is processing of JavaBeans based metamodels. This tutorial shows how to generate code from JavaBeans based metamodels. The example project explained in this tutorial is available for Download here.
First we need to import the Meta Model.
Now we can handle our Meta Model Elements Page, Link and Table. Take a closer look, how we access properties of the Model Elements.
The first part of this expression access the property label of the Bean Link
With other words: On Bean Link we call getLabel(). Then we call the reference containingPage and ask the returned Page for its name
With other words: On Bean Link we call getContainingPage().getName(). Note that we always use the Getter to access the properties. We rename the properties of Page like this:
This will don't affect the Templates, causes the getter don't change.
Part 1: The Meta Model
The Meta Model consists of simple POJO's. Java Classes that contains properties accessed by getter and setter operations. In this simple little showcase we want to model a Web page. So, first of all, we need a Model Element for modelling pages. We name it Page.package simple.javabean.example;
import java.util.List;
public class Page {
}
Ok, but what is a model Element without any attribute? Every Page should have a name. So lets add:
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Also references to other pages should be possible. This is done by Links. Of cause, we allow more then one Link on one Page, we add a List of Links:
private List<Link> links;
public List<Link> getLinks() {
return links;
}
public void setLinks(List<Link> links) {
this.links = links;
}
Beans also can contain operations like:
...
public Link getFirstLink(){
return links != null ? links.get(0) : null;
}
...
At last, every Page should contain a Table. So the final Bean looks like:
package simple.javabean.example;
import java.util.List;
public class Page {
/*
* Set of Properties.
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private List<Link> links;
public List<Link> getLinks() {
return m_links;
}
public void setLinks(List<Link> links) {
this.links = links;
}
private List<Table> tables;
public List<Table> getTables() {
return tables;
}
public void setTables(List<Table> tables) {
this.tables = tables;
}
/*
* Set of Methods
*/
public void addLink(String name, Page referedPage){
//do something
}
public Link getFirstLink(){
return links != null ? links.get(0) : null;
}
}
In fact, we need two other Model Elements, already used by the Page: A Link and a Table.
The Link has an attibute label, a reference named containingPage to the Page containing this Link. A second reference named referedPage contains the referred Page.
package simple.javabean.example;
public class Link {
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
private Page containingPage;
public Page getContainingPage() {
return containingPage;
}
public void setContainingPage(Page containingPage) {
this.containingPage = containingPage;
}
private Page referedPage;
public Page getReferedPage() {
return referedPage;
}
public void setReferedPage(Page referedPage) {
this.referedPage = referedPage;
}
}
The Table has a name and have information about there number of rows and columns. In this little example, we don't need a table with any content :-)
package simple.javabean.example;
public class Table {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int numberOfColumns;
public int getNumberOfColumns() {
return numberOfColumns;
}
public void setNumberOfColumns(int numberOfColumns) {
this.numberOfColumns = numberOfColumns;
}
private int numberOfRows;
public int getNumberOfRows() {
return numberOfRows;
}
public void setNumberOfRows(int numberOfRows) {
this.numberOfRows = numberOfRows;
}
}
Have in mind that we differ between properties that represent an attribute of a Bean like the lable of the Link above on the one side,
...
private String label;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
...
and references to other Model Objects on the other side.
...
private Page referedPage;
public Page getReferedPage() {
return referedPage;
}
public void setReferedPage(Page referedPage) {
this.referedPage = referedPage;
}
...
Our Meta Model is ready.
Part 2: The workflow configuration
We need to configure the workflow right, to handle the JavaBeans Meta Model. The following workflow shows how to use a JavaBeans based MetaModel.<workflow>
<property file="example.properties"/>
<!-- Is used to instance the model. The model is put in the modelSlot 'model'-->
<component class="simple.javabean.example.MyWorkflowComponent">
<modelSlot value="model"/>
</component>
<!-- Run the Generator -->
<component id="generator" class="org.openarchitectureware.xpand2.Generator" skipOnErrors="true">
<!-- The Meta Model is JavaBeans based -->
<metaModel class="org.openarchitectureware.type.impl.java.JavaMetaModel">
<typeStrategy class="org.openarchitectureware.type.impl.java.beans.JavaBeansStrategy"/>
</metaModel>
<fileEncoding value="ISO-8859-1"/>
<!-- Call Define Root in Template Root for our model put in the modleslot 'model' -->
<expand value="oaw::Root::Root FOR model"/>
<outlet path="${srcGenPath}">
</outlet>
</component>
</workflow>
The first line is quite easy. Every workflow (should) have there own property file.
<property file="example.properties"/>
The next few lines are used to call the Workflow Component MyWorkflowComponent. We implement it in the next Part of this HowTo and use it to instantiate a little example model. The model-instance is put into the modelslot model.
<component class="simple.javabean.example.MyWorkflowComponent">
<modelSlot value="model"/>
</component>
The next component is the generator.
<component id="generator" class="org.openarchitectureware.xpand2.Generator" skipOnErrors="true">
<!-- The Meta Model is JavaBeans based -->
<metaModel class="org.openarchitectureware.type.impl.java.JavaMetaModel">
<typeStrategy class="org.openarchitectureware.type.impl.java.beans.JavaBeansStrategy"/>
</metaModel>
<fileEncoding value="ISO-8859-1"/>
<!-- Call Define Root in Template Root for our model put in the modleslot 'model' -->
<expand value="oaw::Root::Root FOR model"/>
<outlet path="${srcGenPath}">
</outlet>
</component>
The interesting lines are:
<metaModel class="org.openarchitectureware.type.impl.java.JavaMetaModel">
<typeStrategy class="org.openarchitectureware.type.impl.java.beans.JavaBeansStrategy"/>
</metaModel>
We use a JavaBeans based MetaModel
<expand value="oaw::Root::Root FOR model"/>
Start generation with Define Root in Template Root for model. Note: model is the modelslot we defined in the MyWorkflowComponent!
Part 3: Instantiate a Model Instance
The simplest way to instantiate a Model instance is to create it during runtime inside a Workflow Component. Therefore we write a Workflow Component MyWorkflowComponent.package simple.javabean.example;
import java.util.ArrayList;
import org.openarchitectureware.workflow.WorkflowContext;
import org.openarchitectureware.workflow.issues.Issues;
import org.openarchitectureware.workflow.lib.WorkflowComponentWithModelSlot;
import org.openarchitectureware.workflow.monitor.ProgressMonitor;
import simple.javabean.example.Link;
import simple.javabean.example.Page;
import simple.javabean.example.Table;
public class MyWorkflowComponent extends WorkflowComponentWithModelSlot {
/**
* Then calling MyWorkflowComponent the invoke method is called. We use it, to instance
* the model and apply it to a modelslot, so it can be used later by the generator component.
*
* @see org.openarchitectureware.workflow.WorkflowComponent#invoke(...[shortened]...)
*/
public void invoke(WorkflowContext wfCxt, ProgressMonitor arg1, Issues arg2) {
//This property contains the model
Page model = createStartPage();
//Apply the model to the model slot
wfCxt.set(getModelSlot(), model);
}
/**
* This method initialises a few instances of pages, links and tables.
*/
private Page createStartPage(){
Page startPage = new Page();
startPage.setName("My_Startpage");
Page refPage = new Page();
refPage.setName("refered page");
Table table = new Table();
table.setName("A_table");
table.setNumberOfColumns(5);
table.setNumberOfRows(8);
startPage.setTables(new ArrayList<Table>());
startPage.getTables().add(table);
Link link = new Link();
link.setLabel("link_Lable");
link.setContainingPage(startPage);
link.setReferedPage(refPage);
startPage.setLinks(new ArrayList<Link>());
startPage.getLinks().add(link);
return startPage;
}
}
This Component has first to instantiate a model and second to put into a model slot, so that later components (here the Generator Component) can use it. With createStartPage() we instantiate a few Model Elements. First a Page My_StartPage is created. Then a Link and a Table are added. Because the Label has two Pages as targets, we add a second Page refered_Page.
Part 4: Templates
In the end of this HowTo we show how to build up Templates for the use with JavaBeans. In our Generator Component we call the Root Template. Lets take a closer look inside this Template:
«REM»Import the JavaBeans MetaModel«ENDREM»
«IMPORT simple::javabean::example»
«REM»This Define simply print out some information«ENDREM»
«DEFINE Root FOR Page»
«FILE "Model.txt"»
Start Page name: '«name»'
----------------------------
Containing '«links.size»' link(s)
«EXPAND Root FOREACH links»
«EXPAND FirstLink FOR firstLink»
----------------------------
Containing '«tables.size»' table(s)
«EXPAND Root FOREACH tables»
«ENDFILE»
«ENDDEFINE»
«DEFINE Root FOR Table»
Name: '«name»' | # rows:«numberOfRows» | # cloumns : «numberOfColumns»
«ENDDEFINE»
«DEFINE Root FOR Link»
Name: '«label»' | from page: '«containingPage.name»' to page: '«referedPage.name»'
«ENDDEFINE»
«DEFINE FirstLink FOR Link»
First link on the page is: «label»
«ENDDEFINE»
«DEFINE Root FOR Object»
«ENDDEFINE»
First we need to import the Meta Model.
«IMPORT simple::javabean::example»
Now we can handle our Meta Model Elements Page, Link and Table. Take a closer look, how we access properties of the Model Elements.
«DEFINE Root FOR Link»
Name: '«label»' | from page: '«containingPage.name»' to page: '«referedPage.name»'
«ENDDEFINE»
The first part of this expression access the property label of the Bean Link
Name: «label»
With other words: On Bean Link we call getLabel(). Then we call the reference containingPage and ask the returned Page for its name
from page: «containingPage.name»
With other words: On Bean Link we call getContainingPage().getName(). Note that we always use the Getter to access the properties. We rename the properties of Page like this:
private String m_name;
public String getName() {
return m_name;
}
public void setName(String name) {
this.m_name = name;
}
This will don't affect the Templates, causes the getter don't change.

