First a closer look at what happens behind the scene, and then I'll put you on the road of writing your own templates.
Three stages
What amalegeni does can be subdivided into 3 stages: 1) using antlr to parse the .mlg file, and convert it to JSON data 2) applying the template on the JSON data, outputting everything into 1 big text 3) chopping up the big text into separate code-files Command-line arguments to amalegeni allow you to call on each stage separately.
Sample data
Suppose we have the following bean/service definition, called 'Done.mlg' (it's the same as 'Todo.mlg' with a few extra beans throw in). Copy/paste the following into a file named Done.mlg.
variable vBaseServicePackage = myapp.server.common;
package myapp.client.generated;
bean TodoBean
{
int todoId;
String description;
int rank;
}
bean AttributeBean
{
String name;
String displayName;
}
bean IdLabel
{
String id;
String label;
}
package myapp.server.generated;
service DoneService
{
List<TodoBean> getTodoList()
<<
select todo_id, description, rank
from t_todo
order by rank
>>
int getNextSequenceValue()
<<
select nextval('seq_todo')
>>
int getMaxRank()
<<
select max(rank) from t_todo
>>
void insertTask( int id, String description, int rank)
<<
insert into t_todo(todo_id, description, rank)
values(?, ?, ?)
>>
int addNewTask(String task)
{{
int newId=getNextSequenceValue();
int newRank=1+getMaxRank();
insertTask(newId,task,newRank);
return newId;
}}
}
Template
Let's get the client/server template for use in this case:
amelegeni -s cs.stg > cs.stg
Stage 1 output
If you want to see what the above 'Done.mlg' looks like in JSON code, then execute this command:
amelegeni -1 Done.mlg
The '1' stands for stage 1 (see top of the page). The whole output can be seen here. Following is an edited version showing ONLY those lines which are of interest to us, for rolling our own template...
{
"serviceName":"DoneService",
"beanList":
[
{ "name":"TodoBean"
, "memberList":[ "todoId","description","rank"]
},
{ "name":"AttributeBean"
, "memberList":[ "name","displayName"]
},
{ "name":"IdLabel"
, "memberList":[ "id","label"]
}
],
"methodList":
[
{ "name":"getTodoList"
, "bodyTypeSqlFlag":"true"
},
{ "name":"getNextSequenceValue"
, "bodyTypeSqlFlag":"true"
},
{ "name":"getMaxRank"
, "bodyTypeSqlFlag":"true"
},
{ "name":"insertTask"
, "bodyTypeSqlFlag":"true"
},
{ "name":"addNewTask"
, "bodyTypeJavaFlag":"true"
}
]
}
Stage 2 output
You could save the output of previous stage into a file, and feed it into amalegeni using the '-2' commandline argument, or you can issue both '-1' and '-2' on the original Done.mlg.
amelegeni -1 -2 -t cs.stg Done.mlg
Since amalegeni is now also generating Java-code, we have to tell it which template to use. The output is all the generated java-code in 1 go, have a look at the result. Examining the output, you'll notice that each 'generated' file is demarcated by a //FILE: tag, like this:
//FILE: myapp/server/generated/DoneServiceImpl.java
And it's up to stage 3 to simply cut up that big file into separate files, and place them in the right directories.
A step further
Explaining everything what follows in detail is beyond the scope of this document, maybe first get yourself acquainted with Terrence Parr's StringTemplate . Save the following template into a file called 'custom.stg' :
group amalegeni;
// ------------------------------------------------------------------
amalegeni() ::= <<
<stBeanCode()>
<stServiceCode()>
>>
// ------------------------------------------------------------------
stBeanCode() ::= <<
<beanList:stBean()>
>>
stBean() ::= <<
<it.name> : <it.memberList:stBeanMember()>
>>
stBeanMember() ::= <<
<it> |
>>
// ----------------------------------------------------------------------
stServiceCode() ::= <<
Service: <<serviceName>>
<methodList:stMethod()>
>>
stMethod() ::= <<
* <if(it.bodyTypeSqlFlag)>SQL: <endif><if(it.bodyTypeJavaFlag)>JAVA: <endif><it.name>()
>>
And now run amalegeni stages 1 and 2 on the above mentioned 'Done.mlg', applying our custom template:
amalegeni -1 -2 -t custom.stg Done.mlg
This is the output:
Using template: custom.stg
TodoBean : todoId | description | rank |
AttributeBean : name | displayName |
IdLabel : id | label |
Service: DoneService
* SQL: getTodoList()
* SQL: getNextSequenceValue()
* SQL: getMaxRank()
* SQL: insertTask()
* JAVA: addNewTask()
Can you put the pieces together? Hint: try and puzzle the Stage 1 output (JSON-data) into the above custom template.. |