-
Notifications
You must be signed in to change notification settings - Fork 70
cobigen core_configuration
CobiGen will be configured using a configuration folder containing a context configuration, multiple template folders with a templates configuration per template folder, and a number of templates in each template folder. Find some examples here. Thus, a simple folder structure might look like this:
CobiGen_Templates
|- templateFolder1
|- templates.xml
|- templateFolder2
|- templates.xml
|- context.xml
The context configuration (context.xml
) always has the following root structure:
<?xml version="1.0" encoding="UTF-8"?>
<contextConfiguration xmlns="http://capgemini.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<triggers>
...
</triggers>
</contextConfiguration>
The context configuration has a version
attribute, which should match the XSD version the context configuration is an instance of. It should not state the version of the currently released version of CobiGen. This attribute should be maintained by the context configuration developers. If configured correctly, it will provide a better feedback for the user and thus higher user experience. Currently there is only the version v1.0. For further version there will be a changelog later on.
As children of the <triggers>
node you can define different triggers. By defining a <trigger>
you declare a mapping between special inputs and a templateFolder
, which contains all templates, which are worth to be generated with the given input.
<trigger id="..." type="..." templateFolder="..." inputCharset="UTF-8" >
...
</trigger>
-
The attribute
id
should be unique within an context configuration. It is necessary for efficient internal processing. -
The attribute
type
declares a specific trigger interpreter, which might be provided by additional plug-ins. A trigger interpreter has to provide an input reader, which reads specific inputs and creates a template object model out of it to be processed by the FreeMarker template engine later on. Have a look at the plug-in’s documentation of your interest and see, which trigger types and thus inputs are currently supported. -
The attribute
templateFolder
declares the relative path to the template folder, which will be used if the trigger gets activated. -
The attribute
inputCharset
(optional) determines the charset to be used for reading any input file.
A trigger will be activated if its matchers hold the following formula:
!(NOT || … || NOT) && AND && … && AND && (OR || … || OR)
Whereas NOT/AND/OR describes the accumulationType of a matcher (see below) and e.g. NOT
means 'a matcher with accumulationType NOT matches a given input'. Thus additionally to an input reader, a trigger interpreter has to define at least one set of matchers, which are satisfyable, to be fully functional. A <matcher>
node declares a specific characteristics a valid input should have.
<matcher type="..." value="..." accumulationType="...">
...
</matcher>
-
The attribute
type
declares a specific type of matcher, which has to be provided by the surrounding trigger interpreter. Have a look at the plug-in’s documentation, which also provides the used trigger type for more information about valid matcher and their functionalities. -
The attribute
value
might contain any information necessary for processing the matcher’s functionality. Have a look at the relevant plug-in’s documentation for more detail. -
The attribute
accumulationType
(optional) specifies how the matcher will influence the trigger activation. Valid values are:-
OR (default): if any matcher of accumulation type OR matches, the trigger will be activated as long as there are no further matchers with different accumulation types
-
AND: if any matcher with AND accumulation type does not match, the trigger will not be activated
-
NOT: if any matcher with NOT accumulation type matches, the trigger will not be activated
-
Finally, a <matcher>
node can have multiple <variableAssignment>
nodes as children. Variable assignments allow to parametrize the generation by additional values, which will be added to the object model for template processing. The variables declared using variable assignments, will be made accessible in the templates.xml as well in the object model for template processing via the namespace variables.*
.
<?xml version="1.0" encoding="UTF-8"?>
<contextConfiguration xmlns="http://capgemini.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<triggers>
<trigger id="..." type="..." templateFolder="...">
<matcher type="..." value="...">
<variableAssignment type="..." key="..." value="..." />
</matcher>
</trigger>
</triggers>
</contextConfiguration>
-
The attribute
type
declares the type of variable assignment to be processed by the trigger interpreter providing plug-in. This attribute enables variable assignments with different dynamic value resolutions. -
The attribute
key
declares the namespace under which the resolved value will be accessible later on. -
The attribute
value
might declare a constant value to be assigned or any hint for value resolution done by the trigger interpreter providing plug-in. For instance, iftype
isregex
, then onvalue
you will assign the matched group number by the regex (1, 2, 3…)
The <containerMatcher>
node is an additional matcher for matching containers of multiple input objects.
Such a container might be a package, which encloses multiple types or---more generic---a model, which encloses multiple elements. A container matcher can be declared side by side with other matchers:
<?xml version="1.0" encoding="UTF-8"?>
<contextConfiguration xmlns="http://capgemini.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<triggers>
<trigger id="..." type="..." templateFolder="..." >
<containerMatcher type="..." value="..." retrieveObjectsRecursively="..." />
<matcher type="..." value="...">
<variableAssignment type="..." variable="..." value="..." />
</matcher>
</trigger>
</triggers>
</contextConfiguration>
-
The attribute
type
declares a specific type of matcher, which has to be provided by the surrounding trigger interpreter. Have a look at the plug-in’s documentation, which also provides the used trigger type for more information about valid matcher and their functionalities. -
The attribute
value
might contain any information necessary for processing the matcher’s functionality. Have a look at the relevant plug-in’s documentation for more detail. -
The attribute
retrieveObjectsRecursively
(optional boolean) states, whether the children of the input should be retrieved recursively to find matching inputs for generation.
The semantics of a container matchers are the following:
-
A
<containerMatcher>
does not declare any<variableAssignment>
nodes -
A
<containerMatcher>
matches an input if and only if one of its enclosed elements satisfies a set of<matcher>
nodes of the same<trigger>
-
Inputs, which match a
<containerMatcher>
will cause a generation for each enclosed element
The template configuration (templates.xml
) specifies, which templates exist and under which circumstances it will be generated. There are two possible configuration styles:
-
Configure the template meta-data for each template file by template nodes
-
(since cobigen-core-v1.2.0): Configure templateScan nodes to automatically retrieve a default configuration for all files within a configured folder and possibly modify the automatically configured templates using templateExtension nodes
To get an intuition of the idea, the following will intially describe the first (more extensive) configuration style. Such an configuration root structure looks as follows:
<?xml version="1.0" encoding="UTF-8"?>
<templatesConfiguration xmlns="http://capgemini.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0" templateEngine="FreeMarker">
<templates>
...
</templates>
<increments>
...
</increments>
</templatesConfiguration>
<templatesConfiguration>
specifies two attributes. The attribute version
provides further usability support and will be handled analogous to the version
attribute of the context configuration. The optional attribute templateEngine
specifies the template engine to be used for processing the templates (since cobigen-core-4.0.0). By default it is set to FreeMarker
.
The node <templatesConfiguration>
allows two different grouping nodes as children. First, there is the <templates>
node, which groups all declarations of templates. Second, there is the <increments>
node, which groups all declarations about increments.
The <templates>
node groups multiple <template>
declarations, which enables further generation. Each template file should be registered at least once as a template to be considered.
<templates>
<template name="..." destinationPath="..." templateFile="..." mergeStrategy="..." targetCharset="..." />
...
</templates>
A template declaration consist of multiple information:
-
The attribute
name
specifies an unique ID within the templates configuration, which will later be reused in the increment definitions. -
The attribute
destinationPath
specifies the destination path the template will be generated to. It is possible to use all variables defined by variable assignments within the path declaration using the FreeMarker syntax${variables.*}
. While resolving the variable expressions, each dot within the value will be automatically replaced by a slash. This behavior is accounted for by the transformations of Java packages to paths as CobiGen has first been developed in the context of the Java world. Furthermore, the destination path variable resolution provides the following additional built-in operators analogue to the FreeMarker syntax:-
?cap_first
analogue to FreeMarker -
?uncap_first
analogue to FreeMarker -
?lower_case
analogue to FreeMarker -
?upper_case
analogue to FreeMarker -
?replace(regex, replacement)
- Replaces all occurrences of the regular expressionregex
in the variable’s value with the givenreplacement
string. (since cobigen-core v1.1.0) -
?removeSuffix(suffix)
- Removes the givensuffix
in the variable’s value iff the variable’s value ends with the givensuffix
. Otherwise nothing will happen. (since cobigen-core v1.1.0) -
?removePrefix(prefix)
- Analogue to?removeSuffix
but removes the prefix of the variable’s value. (since cobigen-core v1.1.0)
-
-
The attribute
templateFile
describes the relative path dependent on the template folder specified in the trigger to the template file to be generated. -
The attribute
mergeStrategy
(optional) can be optionally specified and declares the type of merge mechanism to be used, when thedestinationPath
points to an already existing file. CobiGen by itself just comes with amergeStrategy
override
, which enforces file regeneration in total. Additional available merge strategies have to be obtained from the different plug-in’s documentations (see here for java, XML, properties, and text). Default: not set (means not mergable) -
The attribute
targetCharset
(optional) can be optionally specified and declares the encoding with which the contents will be written into the destination file. This also includes reading an existing file at the destination path for merging its contents with the newly generated ones. Default: UTF-8
(Since version 4.1.0) It is possible to reference external template
(templates defined on another trigger), thanks to using <incrementRef …>
that are explained here.
(since cobigen-core-v1.2.0)
The second configuration style for template meta-data is driven by initially scanning all available templates and automatically configure them with a default set of meta-data. A scanning configuration might look like this:
<?xml version="1.0" encoding="UTF-8"?>
<templatesConfiguration xmlns="http://capgemini.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.2">
<templateScans>
<templateScan templatePath="templates" templateNamePrefix="prefix_" destinationPath="src/main/java"/>
</templateScans>
</templatesConfiguration>
<templateScan …>
nodes for different templatePaths
and different templateNamePrefixes
.
-
The
name
can be specified to later on reference the templates found by a template-scan within an increment. (since cobigen-core-v2.1.) -
The
templatePath
specifys the relative path from thetemplates.xml
to the root folder from which the template scan should be performed. -
The
templateNamePrefix
(optional) defines a common id prefix, which will be added to all found and automatically configured templates. -
The
destinationPath
defines the root folder all found templates should be generated to, whereas the root folder will be a prefix for all found and automatically configured templates.
A templateScan
will result in the following default configuration of templates. For each file found, new template will be created virtually with the following default values:
-
id
: file name without.ftl
extension prefixed bytemplateNamePrefix
fromtemplate-scan
-
destinationPath
: relative file path of the file found with the prefix defined bydestinationPath
fromtemplate-scan
. Furthermore,-
it is possible to use the syntax for accessing and modifying variables as described for the attribute
destinationPath
of the template node, besides the only difference, that due to file system restrictions you have to replace all?
-signs (for built-ins) with#
-signs. -
the files to be scanned, should provide their final file-ending by the following file naming convention:
<filename>.<fileending>.ftl
Thus the file-ending.ftl
will be removed after generation.
-
-
templateFile
: relative path to the file found -
mergeStrategy
: (optional) not set means not mergable -
targetCharset
: (optional) defaults to UTF-8
(Since version 4.1.0) It is possible to reference external templateScan
(templateScans defined on another trigger), thanks to using <incrementRef …>
that are explained here.
(since cobigen-core-v1.2.0)
Additionally to the templateScan declaration it is easily possible to rewrite specific attributes for any scanned and automatically configured template.
<templates>
<templateExtension ref="prefix_FooClass.java" mergeStrategy="javamerge" />
</templates>
<templateScans>
<templateScan templatePath="foo" templateNamePrefix="prefix_" destinationPath="src/main/java/foo"/>
</templateScans>
Lets assume, that the above example declares a template-scan
for the folder foo
, which contains a file FooClass.java.ftl
in any folder depth. Thus the template scan will automatically create a virtual template declaration with id=prefix_FooClass.java
and further default configuration.
Using the templateExtension
declaration above will reference the scanned template by the attribute ref
and overrides the mergeStrategy
of the automatically configured template by the value javamerge
. Thus we are able to minimize the needed templates configuration.
(Since version 4.1.0) It is possible to reference external templateExtension
(templateExtensions defined on another trigger), thanks to using <incrementRef …>
that are explained here.
The <increments>
node groups multiple <increment>
nodes, which can be seen as a collection of templates to be generated. An increment will be defined by a unique id
and a human readable description
.
<increments>
<increment id="..." description="...">
<incrementRef ref="..." />
<templateRef ref="..." />
<templateScanRef ref="..." />
</increment>
</increments>
An increment might contain multiple increments and/or templates, which will be referenced using <incrementRef …>
, <templateRef …>
, resp. <templateScanRef …>
nodes. These nodes only declare the attribute ref
, which will reference an increment, a template, or a template-scan by its id
or name
.
(Since version 4.1.0) An special case of <incrementRef …>
is the external incrementsRef. By default, <incrementRef …>
are used to reference increments defined in the same templates.xml
file. So for example, we could have:
<increments>
<increment id="incA" description="...">
<incrementRef ref="incB" />
</increment>
<increment id="incB" description="...">
<templateRef .... />
<templateScan .... />
</increment>
</increments>
However, if we want to reference an increment that it is not defined inside our templates.xml
(an increment defined for another trigger), then we can use external incrementRef as shown below:
<increment name="..." description="...">
<incrementRef ref="trigger_id::increment_id"/>
</increment>
The ref string is split using as delimiter ::
. The first part of the string, is the trigger_id
to reference. That trigger contains an increment_id
. Currently, this functionality only works when both templates use the same kind of input file.
since cobigen-core-3.0.0 which is included in the Eclipse and Maven Plugin since version 2.0.0
In addition, it is possible to implement more complex template logic by custom Java code. To enable this feature, you can simply import the the CobiGen_Templates
by clicking on Adapt Templates, turn it into a simple maven project (if it is not already) and implement any Java logic in the common maven layout (e.g. in the source folder src/main/java
). Each Java class will be instantiated by CobiGen for each generation process. Thus, you can even store any state within a Java class instance during generation. However, there is currently no guarantee according to the template processing order.
As a consequence, you have to implement your Java classes with a public default (non-parameter) constructor to be used by any template. Methods of the implemented Java classes can be called within templates by the simple standard FreeMarker expression for calling Bean methods: SimpleType.methodName(param1)
. Until now, CobiGen will shadow multiple types with the same simple name indeterministically. So please prevent yourself from that situation.
Finally, if you would like to do some reflection within your Java code accessing any type of the template project or any type referenced by the input, you should load classes by making use of the classloader of the util classes. CobiGen will take care of the correct classloader building including the classpath of the input source as well as of the classpath of the template project. If you use any other classloader or build it by your own, there will be no guarantee, that generation succeeds.
since cobigen-core-4.0.0
Using a configuration with template scan, you can make use of properties in templates specified in property files named cobigen.properties
next to the templates. The property files are specified as Java property files. Property files can be nested in subfolders. Properties will be resolved including property shading. Properties definied nearest to the template to be generated will take precedence.
In addition, a cobigen.properties
file can be specified in the target folder root (in eclipse plugin, this is equal to the source project root). These properties take precedence over template properties specified in the template folder.
Note
|
It is not allowed to override context variables in cobigen.properties specifications as we have not found any interesting use case. This is most probably an error of the template designer, CobiGen will raise an error in this case.
|
since cobigen-core-4.0.0
One special property you can specify in the template properties is the property relocate
. It will cause the current folder and its subfolders to be relocated at destination path resolution time. Take the following example:
folder
- sub1
Tempalte.java.ftl
cobigen.properties
Let the cobigen.properties
file contain the line relocate=../sub2/${cwd}
. Given that, the relative destination path of Template.java.ftl
will be resolved to folder/sub2/Template.java
. Compare template scan configuration for more information about basic path resolution. The relocate
property specifies a relative path from the location of the cobigen.properties
. The ${cwd}
placeholder will contain the remaining relative path from the cobigen.properties
location to the template file. In this basic example it just contains Template.java.ftl
, but it may even be any relative path including subfolders of sub1 and its templates.
Given the relocate
feature, you can even step out of the root path, which in general is the project/maven module the input is located in. This enables template designers to even adress, e.g., maven modules located next to the module the input is coming from.
In addition to what is served by the different model builders of the different plug-ins, CobiGen provides a minimal model based on context variables as well as CobiGen properties. The following model is independent of the input format and will be served as a template model all the time:
-
variables
-
all triggered context variables mapped to its assigned/mapped value
-
-
all simple names of Java template logic implementation classes
-
all full qualified names of Java template logic implementation classes
-
further input related model, e.g. model from Java inputs
Since cobigen-core 4.1.0, we changed the plug-in discovery mechanism. So far it was necessary to register new plugins programmatically, which introduces the need to let every tool integration, i.e. for eclipse or maven, be dependent on every plug-in, which should be released. This made release cycles take long time as all plug-ins have to be integrated into a final release of maven or eclipse integration.
Now, plug-ins are automatically disovered by the Java Service Loader mechanism from the classpath. This also effects the setup of eclipse and maven integrations to allow modular releases of CobiGen in future. We are now able to provide faster rollouts of bugfixes in any of the plug-ins as they can be released completely independently.
Disclaimer
If you discover any documentation bugs or would like to request new content, please raise them as an issue or create a pull request. Contributions to this wiki are done through the main repo under the folder documentation.
License
This documentation is licensed under the Creative Commons License (Attribution-NoDerivatives 4.0 International
)