Hi,
Currently I am developing new activity steps to enable a more flexible code generator. Practically it is a code generator workflow. My old code generator is an activity step and does the stuff at one step. That steps in the code are as follows:
- 1.) Get the identifier for the current application (by the value given as parameter ’source value’)
- 2.) Save the current working directory
- 3.) Get values ‘UMLImportDBName’, ‘UMLImportDBUser’ and ‘UMLImportDBPass’ from the active document (that by the active application). These are modifiable and stored by the properties of the application.
- 4.) Save the current mode (database / local document file) and switch to database to export actual contents.
- 5.) Reload the application model from database into the internal object model and set back the original mode.
- 6.) Retrieve the application identifier from the applications model by it’s application name ’source value’ of the action and store it in a local variable.
- 7.) Get the value of the XSLT directory where the action has to be performed ‘codegenbasedir’. Do this optionally by direct database read if it is not in the list of application parameters.
- 8.) Put the identifier as a variable in the active document ‘SaveApplicationID’.
- 9.) Call a registered event handler by it’s name ‘exportApplicationToXMLBuffer’
- 10.) Get the result ‘memorybuffer’ that the handler has stored in the input parameter container (not the result container).
- 11.) Also get the file name the handler has stored ‘filename’.
- 12.) Change to the working directory the XSLT transformation should perform ‘codegenbasedir’.
- 13.) Perform the XSLT transformation and save the result to stdout.
The enumeration doesn’t work
You can spot the point of inflexibility as it is clear. The function does too much and expects the XSLT transformation generates files. The activity step cannot be used to cascade several code generators to enable M2M transformations. And extending the existing one is the wrong way, because it will become a monster and keep being not flexible.
It would be much more flexible if I split the steps and use them to model the code generator workflow in an UML Activity diagram. I have demonstrated workflow activities earlier by enabling validation in business forms (more in PDF version chapter ‘Applying business rules’ – sorry for the typo). That is, I enable modeling of validation rules rather than coding them. With a short view about that, it is much more work to ‘code’ in UML Activity diagrams, but at a longer and deeper view it raises the abstraction level and with a M2M transformation it will also ease the modeling.
That is exactly the cause I start writing new activity steps that could be used in an activity or to name it also workflow.
One action of the above steps would be getting the identifier from the current row in the database form. But it is more difficult than you may expect. It is the complexity of the SQL query I rely on. What I need is to get the primary key column out of the current query object that represents the value I match against ’source value’ – and it’s ’source column’. In my actual scope it is the application name to generate code for and it is not declared as an unique column.
A simple solution would be to make that column unique and complain if it is not. That would make the workflow more easy. That solved, I ask my self about the place where I implement the stuff to get that identifier.
So currently I think about extensions of my database classes to ease the modification of a given SQL query. But how to start and what solutions may be the best. When the database query is simple, I may choose simple string splitting to get the columns and then add new columns for sample. But what happens if the given query contains sub queries or joins?
If the given column and value points to a detail table it still may not complain about not unique values. But rather it is a design error of the code generator workflow parameter passing definition (don’t think about wrong templates used yet).
It simply points to a detail value not one of the master values in a join. The transformation may work but also may not work by the given identifier. It is a scope problem and it is not strongly typed.
So if a form contains SQL joins and I use columns from the detail side (I think the right side in the join), then the scope problem arises. Thus I must not only test against uniqueness but also against the fact not using values from the detail side (tables referencing to master side – or the left).
Some of the resulting code – I hope doing it right – will be in database classes, but other stuff may rather be placed in a separate action step to enable designing validation against the intention of the workflow. An action step to retrieve the identifier therefore may not only return the value, but also return some more values, such as what primary key column was used and what table the column is from. Also it may return the primary table if a join or other circumstance results in a multi table query.
So you see it is not easy to write this action step and you also see, it is only the first step
And I cannot expect too much in the scope. What is if one uses a ready made workflow at the wrong place and tries to pass a value he / she configures? I cannot expect an ‘application name’ and try to get the identifier from the application table. It will fail on forms. A good use case to start generating code at the scope of a form would be predesigning the form in a different format – like DialogBlocks. The workflow therefore may create a single form project in DialogBlocks, let the user design while waiting for the application and then reverse the design to gather probably new fields to be optionally added to the database model. That said, you not only change the scope where to start code generation, you also need more flexibility by waiting for an application and using a reverse engineering step to collect new fields and possibly also a new order or complete new design that must use a XML based form in the prototype to directly present the design.
What I can say, you will get plenty of ideas if you can simply do it. Also a code generator model / workflow is language and implementation neutral, thus you could probably design you own tool by supporting a suitable code generator converting the model into real code of your choice.
For any questions, please contact my via Twitter.