-
Notifications
You must be signed in to change notification settings - Fork 4
MOGLiCC Tutorial Part C
Let's assume that the requirements exist, that 1. not only one big sql statement is needed but that 2. each insert statements must be available in a separate file and, moreover, that 3. for each database table an insert.sql is required bundling all insert statements of the respective table. To realize these two new features, one could use the ModelBasedLineInserter, but for each model class a separate input artefact would be necessary. This solution is very inefficient. Therefore, we will apply the ClassBasedFileMaker which is much smarter in this case!
1 - The very first thing to do now is to create a new template file for the ClassBasedFileMaker. For this purpose create the file /input/VelocityClassBasedFileMaker/InsertSQL/Main.tpl with the following content:
@TargetFileName $classDescriptor.name.sql
@NameOfValidModel InsertSQL
@CreateNew true
#set( $tableName = $classDescriptor.getMetaInfoValueFor("tableName") )
INSERT INTO $tableName ($commaSeparatedListOfAttributes) VALUES ($commaSeparatedListOfTableValues);
The content of the InsertSQL folder represents the input artefact for the VelocityClassBasedFileMaker.
2 - After executing MOGLiCC, several observations are worth making. Firstly, the generation report tells us that the FileMaker plugin has been active. Unfortunately, the file name is faulty. Secondly, since no property @targetDir is provided in the template header, the generation result is only present in the plugin's output directory /input/VelocityClassBasedFileMaker/InsertSQL. Thirdly, the content of the generated file contains only one line and the used Velocity variables could obviously not be replaced. What we do now is, that we correct the value of the @TargetFileName property. Velocity allows two syntax alternatives for using a variable:
# this alternative is more readable, but requires a space or linebreak behind it
$firstSyntaxForCallingAVelocityVariable
# this alternative is less readable, but appropriate to embed its use into a sequence of chars
${secondSyntaxForCallingAVelocityVariable}
To get along in our situation we apply the second alternative:
@TargetFileName ${classDescriptor.name}.sql
3 - After rerunning MOGLiCC, for each class in the model file a sql file has been generated:
InsertStatment.1.sql
InsertStatment.2.sql
InsertStatment.3.sql
InsertStatment.4.sql
InsertStatment.5.sql
It is good practise to use filenames read from metainfos, however, since you have learned to do so in a previous tutorial part, we skip that here. For the ongoing tutorial you should skip that too, in order to avoid deviations from later tutorial parts. Instead, we care now and here about the file contents.
Go back to the Main.tpl of the VelocityModelBasedLineInserter and view the template body. It contains an outer and an inner foreach loop. Copy all the content within the outer loop (i.e. from setting the tableName variable until the INSERT INTO output line) and replace the existing template body of the Main.tpl of the FileMaker by this copy. Note, that the FileMaker is implemented to be ClassBased. It does not need the whole model, instead its templates can address the classDescriptors directly! Having started MOGLiCC you find that all FileMaker made output files contain the correct content and the first goal of the tutorial part is already attained.
4 - Bundling only a part of the model classes is a bit tricky. Firstly, we have to introduce for each database table a new model class. Secondly, in order to destinguish between the already existing insert model classes and the new bundle model classes, we have to introduce a model class type as a new metainfo. These modification drives the model file to look like that:
model InsertSQL
metainfo resultFileName insert.sql
# bundle model classes
class SQLBundle.1
metainfo classType bundle
metainfo tableName REMITTER
class SQLBundle.2
metainfo classType bundle
metainfo tableName ORDER
# insert model classes
class InsertStatement.1
metainfo classType insert
metainfo tableName REMITTER
attribute ID
...
...
...
5 - The templates (both the FileMaker and the LineInserter one) need consequent adaptation. The existing templates (Main.tpl) have been implemented to process only the insert model classes. Therefore, they should ignore the bundle model classes. For the FileMaker, this can easily be achieved by introducing a new property in the model header:
@SkipGeneration bundle == $classDescriptor.getMetaInfoValueFor("classType")
This will make the FileMaker supressing the creation of the result file, but only the creation - model and template are merged anyway! Therefore, a StringIndexOutOfBoundsException at line 37, column 73 is reported, when running MOGLiCC. To avoid that, we have to pimp the template code where the last comma is cut by the Velocity-if-instructions:
#set( $numberOfChars = $commaSeparatedListOfAttributes.length() - 2 )
#if( $numberOfChars > 0)
#set( $commaSeparatedListOfAttributes = $commaSeparatedListOfAttributes.substring(0, $numberOfChars) )
#end
#set( $numberOfChars = $commaSeparatedListOfTableValues.length() - 2 )
#if( $numberOfChars > 0)
#set( $commaSeparatedListOfTableValues = $commaSeparatedListOfTableValues.substring(0, $numberOfChars) )
#end
This template pimping is necessary both in the template of the LineInserter and the FileMaker. Finally, the LineInserter must ignore the bundle classes. This is done by the following template code:
#set( $tableName = $classDescriptor.getMetaInfoValueFor("tableName") )
#set( $classType = $classDescriptor.getMetaInfoValueFor("classType") )
#if( $classType.equals("insert") )
INSERT INTO $tableName ($commaSeparatedListOfAttributes) VALUES ($commaSeparatedListOfTableValues);
#end
Eventually, you can run MOGLiCC without error, all previous result files are correctly generated, but the bundled sql files are still missing.
6 - For creating the bundled sql files we need a new FileMaker input artefact. Create the file /input/VelocityClassBasedFileMaker/BundledSQL/Main.tpl with the following content:
#set( $table = $classDescriptor.getMetaInfoValueFor("tableName") )
@TargetFileName ${table}.sql
@NameOfValidModel InsertSQL
@CreateNew true
@SkipGeneration insert == $classDescriptor.getMetaInfoValueFor("classType")
prompt insert statements for table $table:
This creates new output artefacts in /output/VelocityClassBasedFileMaker/BundleSQL, for each database table (i.e. each bundle model class) a separate file.
7 What's left is the contents of the new output artefacts. Copy the complete body of the Main.tpl of the LineInserter and add it to the body of the BundleSQL/Main.tpl. Finally, add the table check to the following if-clause:
#if( $classType.equals("insert") && $tableName.equals($table))
INSERT INTO $tableName ($commaSeparatedListOfAttributes) VALUES ($commaSeparatedListOfTableValues);
#end
The result file will now have the desired content. :-)
8 - In the very end, we want to have all output artefacts in one target directory. For that purpose we modify the three input artefacts like that:
VelocityModelBasedLineInserter/InsertSQL/Main.tpl:
@TargetDir <applicationRootDir>/InsertSQL
VelocityClassBasedFileMaker/InsertSQL/Main.tpl:
@TargetDir <applicationRootDir>/InsertSQL/singleStatements
VelocityClassBasedFileMaker/BundleSQL/Main.tpl:
@TargetDir <applicationRootDir>/InsertSQL/bundledStatements
Rerun MOGLiCC and have a look. That's it!