-
Notifications
You must be signed in to change notification settings - Fork 70
cobigen javaplugin
The CobiGen Java Plug-in comes with a new input reader for java artifacts, new java related trigger and matchers, as well as a merging mechanism for Java sources.
The Java Plug-in provides a new trigger for Java related inputs. It accepts different representations as inputs (see Java input reader) and provides additional matching and variable assignment mechanisms. The configuration in the context.xml
for this trigger looks like this:
-
type 'java'
Example of a java trigger definition<trigger id="..." type="java" templateFolder="..."> ... </trigger>
This trigger type enables Java elements as inputs.
With the trigger you might define matchers, which restrict the input upon specific aspects:
-
type
fqn
→ full qualified name matchingExample of a java trigger definition with a full qualified name matcher<trigger id="..." type="java" templateFolder="..."> <matcher type="fqn" value="(.+)\.persistence\.([^\.]+)\.entity\.([^\.]+)"> ... </matcher> </trigger>
This trigger will be enabled if the full qualified name (
fqn
) of the declaring input class matches the given regular expression (value
). -
type 'package' → package name of the input
Example of a java trigger definition with a package name matcher<trigger id="..." type="java" templateFolder="..."> <matcher type="package" value="(.+)\.persistence\.([^\.]+)\.entity"> ... </matcher> </trigger>
This trigger will be enabled if the package name (
package
) of the declaring input class matches the given regular expression (value
). -
type 'expression'
Example of a java trigger definition with a package name matcher<trigger id="..." type="java" templateFolder="..."> <matcher type="expression" value="instanceof java.lang.String"> ... </matcher> </trigger>
This trigger will be enabled if the expression evaluates to true. Valid expressions are
-
instanceof fqn
: checks an 'is a' relation of the input type -
isAbstract
: checks, whether the input type is declared abstract
Additionally, the java plugin provides the ability to match packages (containers) as follows:
-
type 'package'
Example of a java trigger definition with a container matcher for packages<trigger id="..." type="java" templateFolder="..."> <containerMatcher type="package" value="com\.example\.app\.component1\.persistence.entity" /> </trigger>
The container matcher matches packages provided by the type
com.capgemini.cobigen.javaplugin.inputreader.to.PackageFolder
with a regular expression stated in thevalue
attribute. (SeecontainerMatcher
semantics to get more information aboutcontainerMatchers
itself.)
Furthermore, it provides the ability to extract information from each input for further processing in the templates. The values assigned by variable assignments will be made available in template and the destinationPath
of context.xml
through the namespace variables.<key>
. The Java Plug-in currently provides two different mechanisms:
-
type 'regex' → regular expression group
<trigger id="..." type="java" templateFolder="..."> <matcher type="fqn" value="(.+)\.persistence\.([^\.]+)\.entity\.([^\.]+)"> <variableAssignment type="regex" key="rootPackage" value="1" /> <variableAssignment type="regex" key="component" value="2" /> <variableAssignment type="regex" key="pojoName" value="3" /> </matcher> </trigger>
This variable assignment assigns the value of the given regular expression group number to the given key
.
-
type 'constant' → constant parameter
<trigger id="..." type="java" templateFolder="..."> <matcher type="fqn" value="(.+)\.persistence\.([^\.]+)\.entity\.([^\.]+)"> <variableAssignment type="constant" key="domain" value="restaurant" /> </matcher> </trigger>
This variable assignment assigns the value
to the key
as a constant.
The CobiGen Java Plug-in implements an input reader for parsed java sources as well as for java Class<?>
objects (loaded by reflection). So API user can pass Class<?>
objects as well as JavaClass
objects for generation. The latter depends on QDox, which will be used for parsing and merging java sources. For getting the right parsed java inputs you can easily use the JavaParserUtil
, which provides static functionality to parse java files and get the appropriate JavaClass
object.
Furthermore, due to restrictions on both inputs according to model building (see below), it is also possible to provide an array of length two as an input, which contains the Class<?>
as well as the JavaClass
object of the same class.
No matter whether you use reflection objects or parsed java classes as input, you will get the following object model for template creation:
-
classObject
('Class' :: Class object of the Java input) -
POJO
-
name ('String' :: Simple name of the input class)
-
package ('String' :: Package name of the input class)
-
canonicalName
('String' :: Full qualified name of the input class) -
annotations ('Map<String, Object>' :: Annotations, which will be represented by a mapping of the full qualified type of an annotation to its value. To gain template compatibility, the key will be stored with '_' instead of '.' in the full qualified annotation type. Furthermore, the annotation might be recursively defined and thus be accessed using the same type of mapping. Example
${pojo.annotations.javax_persistence_Id}
) -
JavaDoc ('Map<String, Object>') :: A generic way of addressing all available JavaDoc doclets and comments. The only fixed variable is
comment
(see below). All other provided variables depend on the doclets found while parsing. The value of a doclet can be accessed by the doclets name (e.g.${…JavaDoc.author}
). In case of doclet tags that can be declared multiple times (currently@param
and@throws
), you will get a map, which you access in a specific way (see below).-
comment ('String' :: JavaDoc comment, which does not include any doclets)
-
params ('Map<String,String> :: JavaDoc parameter info. If the comment follows proper conventions, the key will be the name of the parameter and the value being its description. You can also access the parameters by their number, as in
arg0
,arg1
etc, following the order of declaration in the signature, not in order of JavaDoc) -
throws ('Map<String,String> :: JavaDoc exception info. If the comment follows proper conventions, the key will be the name of the thrown exception and the value being its description)
-
-
extendedType
('Map<String, Object>' :: The supertype, represented by a set of mappings (sincecobigen-javaplugin v1.1.0
)-
name ('String' :: Simple name of the supertype)
-
canonicalName
('String' :: Full qualified name of the supertype) -
package ('String' :: Package name of the supertype)
-
-
implementedTypes
('List<Map<String, Object>>' :: A list of allimplementedTypes
(interfaces) represented by a set of mappings (sincecobigen-javaplugin v1.1.0
)-
interface ('Map<String, Object>' :: List element)
-
name ('String' :: Simple name of the interface)
-
canonicalName
('String' :: Full qualified name of the interface) -
package ('String' :: Package name of the interface)
-
-
-
fields ('List<Map<String, Object>>' :: List of fields of the input class) (renamed since
cobigen-javaplugin v1.2.0
; previously attributes)-
field ('Map<String, Object>' :: List element)
-
name ('String' :: Name of the Java field)
-
type ('String' :: Type of the Java field)
-
canonicalType
('String' :: Full qualified type declaration of the Java field’s type) -
'
isId
' (Deprecated
::boolean
:: true if the Java field or its setter or its getter is annotated with thejavax.persistence.Id
annotation, false otherwise. Equivalent to${pojo.attributes[i].annotations.javax_persistence_Id?has_content}
) -
JavaDoc (see
pojo.JavaDoc
) -
annotations (see
pojo.annotations
with the remark, that for fields all annotations of its setter and getter will also be collected)
-
-
-
methodAccessibleFields
('List<Map<String, Object>>' :: List of fields of the input class or its inherited classes, which are accessible using setter and getter methods)-
same as for field (but without JavaDoc!)
-
-
methods ('List<Map<String, Object>>' :: The list of all methods, whereas one method will be represented by a set of property mappings)
-
method ('Map<String, Object>' :: List element)
-
name ('String' :: Name of the method)
-
JavaDoc (see
pojo.JavaDoc
) -
annotations (see
pojo.annotations
)
-
-
-
Furthermore, when providing a Class<?>
object as input, the Java Plug-in will provide additional functionalities as template methods (deprecated):
-
isAbstract(String fqn)
(Checks whether the type with the given full qualified name is an abstract class. Returns a Boolean value.) (sincecobigen-javaplugin v1.1.1
) (deprecated) -
isSubtypeOf(String subType, String superType)
(Checks whether thesubType
declared by its full qualified name is a sub type of thesuperType
declared by its full qualified name. Equals the Java expressionsubType instanceof superType
and so also returns a Boolean value.) (sincecobigen-javaplugin v1.1.1
) (deprecated)
As stated before both inputs (Class<?>
objects and JavaClass
objects ) have their restrictions according to model building. In the following these restrictions are listed for both models, the ParsedJava
Model which results from an JavaClass
input and the ReflectedJava
Model, which results from a Class<?> input.
It is important to understand, that these restrictions are only present if you work with either Parsed Model OR the Reflected Model. If you use the Maven Build Plug-in or Eclipse Plug-in these two models are merged together so that they can mutually compensate their weaknesses.
-
annotations of the input’s supertype are not accessible due to restrictions in the QDox library. So
pojo.methodAccessibleFields[i].annotations
will always be empty for super type fields. -
annotations' parameter values are available as Strings only (e.g. the Boolean value
true
is transformed into"true"
). This also holds for the Reflected Model. -
fields of "supertypes" of the input
JavaClass
are not available at all. Sopojo.methodAccessibleFields
will only contain the input type’s and the direct superclass’s fields. -
[resolved, since
cobigen-javaplugin 1.3.1
] field types of supertypes are always canonical. Sopojo.methodAccessibleFields[i].type
will always provide the same value aspojo.methodAccessibleFields[i].canonicalType
(e.g.java.lang.String
instead of the expectedString
) for super type fields.
-
annotations' parameter values are available as Strings only (e.g. the Boolean value
true
is transformed into"true"
). This also holds for the Parsed Model. -
annotations are only available if the respective annotation has
@Retention(value=RUNTIME)
, otherwise the annotations are to be discarded by the compiler or by the VM at run time. For more information see RetentionPolicy. -
information about generic types is lost. E.g. a field’s/ methodAccessibleField’s type for
List<String>
can only be provided asList<?>
.
The Java Plug-in provides two additional merging strategies for Java sources, which can be configured in the templates.xml
:
-
Merge strategy
javamerge
(merges two Java resources and keeps the existing Java elements on conflicts) -
Merge strategy
javamerge_override
(merges two Java resources and overrides the existing Java elements on conflicts)
In general merging of two Java sources will be processed as follows:
Precondition of processing a merge of generated contents and existing ones is a common Java root class resp. surrounding class. If this is the case this class and all further inner classes will be merged recursively. Therefore, the following Java elements will be merged and conflicts will be resolved according to the configured merge strategy:
-
extends
andimplements
relations of a class: Conflicts can only occur for the extends relation. -
Annotations of a class: Conflicted if an annotation declaration already exists.
-
Fields of a class: Conflicted if there is already a field with the same name in the existing sources. (Will be replaced / ignored in total, also including annotations)
-
Methods of a class: Conflicted if there is already a method with the same signature in the existing sources. (Will be replaced / ignored in total, also including annotations)
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
)