Skip to content

MOGLiCC Tutorial Part C

iks github user edited this page Mar 3, 2016 · 29 revisions

C) Applying the ClassBasedFileMaker: Separating class specific output

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 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 now do is, that we correct the value of the @TargetFileName property. Velocity has to 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 this 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.

4 - 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) and replace the existing template body of the Main.tpl of VelocityClassBasedFileMaker the 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.

5 - Bundling only a part of the model classes is bit tricky. Firstly, we have to introduce for each database table a new model class. Secondly, in order to destinguish between the already old 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 template (both FileMaker and LineInserter) 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 only supressing the creation of the result file, not the merging of model and templates. Therefore, a StringIndexOutOfBoundsException at line 37, column 73 is report, when running MOGLiCC. To avoid that, we have to pimp the template code where the last comma is cut by 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 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 correct generated, but the bundle sql files are still missing.

Back to the tutorial main page

Next tutorial part

Clone this wiki locally