Introduction
In the third part of the tutorial I will provide one ready template, which can generate source files. I will explain each part of it and what it does. In the previous post we saw the headers template. Here we present the source template.
The source template
Below is the complete code for the Source template. You need to create one Xpand template, name it SourceTemplate.xpt and fill it with the code below:
«REM» Name: SourceTemplate.xpt Description: This template is used to generate source files for the classes Creation Date: 2/21/2020 Created By: Ahmed Karairbahimov Last Update: 2/21/2020 Updated By: Ahmed Karaibrahimov «ENDREM» «IMPORT ecore» «DEFINE CreateSourceFile FOR EClass» «FILE "src/" + name + ".cpp"» //================================================================================================================ // Copyright <2020> <Ahmed Karaibrahimov> // Permission is hereby granted, free of charge, to any person obtaining a copy of this software // and associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all copies or substantial // portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //================================================================================================================ #include «name».hpp «EXPAND templates::HeaderTemplate::GenerateNamespace(true) FOR this» // Argumented constructor «name»::«name»(«EXPAND templates::HeaderTemplate::GetAllConstructorArguments FOR this») : «EXPAND GetAllConstructorArgumentsInitialization FOR this» { } // Getters and setters «EXPAND CreateAllGettersAndSettersImplementation FOR this» «EXPAND templates::HeaderTemplate::GenerateNamespace(false) FOR this» «ENDFILE» «ENDDEFINE» «REM»List all the member initializations«ENDREM» «DEFINE GetAllConstructorArgumentsInitialization FOR EClass» «FOREACH this.eAllAttributes AS attribute ITERATOR iter» m_«attribute.name»{«attribute.name»}«IF iter.counter1 < this.eAttributes.size»,«ENDIF» «ENDFOREACH» «IF eAllAttributes.size > 0 && eAllReferences.size > 0»,«ENDIF» «FOREACH this.eAllReferences AS reference ITERATOR iter» m_«reference.name»{«reference.name»}«IF iter.counter1 < this.eAllReferences.size»,«ENDIF» «ENDFOREACH» «ENDDEFINE» «REM»Generate all the getters and setters implementations«ENDREM» «DEFINE CreateAllGettersAndSettersImplementation FOR EClass» «FOREACH this.eAllAttributes AS attribute» «IF attribute.upperBound == -1»std::vector<«ENDIF» «attribute.eType.name» «IF attribute.upperBound == -1»>«ENDIF» «name»::get«attribute.name»() const { return m_«attribute.name»; } void «name»::set«attribute.name»( «IF attribute.upperBound == -1»std::vector<«ENDIF» «attribute.eType.name» «IF attribute.upperBound == -1»>«ENDIF» value) { m_«attribute.name» = value; } «ENDFOREACH» «FOREACH this.eAllReferences AS reference» «IF reference.upperBound == -1»std::vector<«ENDIF» «reference.eType.name» «IF reference.upperBound == -1»>«ENDIF» «name»::get«reference.name»() const { return m_«reference.name»; } void «name»::set«reference.name»( «IF reference.upperBound == -1»std::vector<«ENDIF» «reference.eType.name» «IF reference.upperBound == -1»>«ENDIF» value) { m_«reference.name» = value; } «ENDFOREACH» «ENDDEFINE»
The source template description
[Lines 1-9] of the source template
The first section that we have is a commented code. I have added some information about the template. It is inside «REM»«ENDREM» blocks which means that the generator will not process this section.
[Line 11]
Here we import the ecore package in order to have access to its member classes. We use for example the EClass in the functions which is part of the ecore package.
[Lines 14-51]
Here is the definition of a function, which we can call from outside. The main template will call this function from its main method and it will take care of the source files generation. First thing that we put in this function is the FILE block, which takes care of saving the template content to a file. We provide it with the file name plus additionally a directory if we want. In this case it will save the content inside a src directory in a file with the name equal to the EClass object plus .cpp. In the ecore model we have a class named TranslationsType. It will create a file named TranslationsType.cpp inside the include directory and will fill it with the following content.
[Lines 16-33]
There is some licensing information.
[Lines 35-37]
First we have inclusion of the class header file. Next we have generation of the namespaces. As you can see here, we are calling a function from another template. The way to call a function from a different template is to provide the path to it. The path shall include the directories and the template name separated by ::. In our example first we have the folder name, which is templates, right after it is the separator and then the template name, excluding the .xpt extension. Lastly, we have the name of the function.
[Lines 39-44]
Here we have the implementation of the constructor with arguments. In this implementation we include the initialization of the class member variables. For this we have created a separate function, implemented in the same template.
[Line 47]
There is a function I have added, which takes care of generating the implementations of the getter and the setters for the member variables.
[Line 49-51]
The function ends with closing the namespaces and closing the tags for the File and the function definition.
[Lines 53-62]
This function is used to generate the members initialization, which is done in the constructor. At the end it will generate something like this for each member variable: m_member{member}, where m_member is the name of the member variable and member is the name of the respective argument. The function goes through each attribute and reference member of the given class, using the FOREACH block and just generates its member initialization.
[Lines 64-102]
The next function generates the implementations of the member variables’ getters and setters. The implementation is a simple one. For the getter it just returns the member variable and for the setter it sets it to the provided value. Of course, you can update and make the implementation more sophisticated. Again we use two FOREACH blocks (one for the attributes and one for the references), go through each member and generate the getter and setter for that particular member.
Conclusion
In this tutorial we saw one complete template, used to generated the source files for the classes. We keep it simpler, but you can always go ahead and make it more sophisticated. You already saw in the previous post most of the Xpand specific components so by now you should be familiar with them. In the next post we will see how to call the functions from the header and source templates and generate the code.

Passionate developer, loving husband and caring father. As an introvert programming is my life. I work as a senior software engineer in a big international company. My hobbies include playing computer games (mostly World of Warcraft), watching TV series and hiking.