Skip to content

howto_create a new plugin

Rubén Díaz edited this page Sep 15, 2017 · 12 revisions

Implementing a new Plug-in

New plug-ins can implement an input reader, a merger, a matcher, a trigger interpreter, and/or a template engine as explained here. TODO: dead link + please adapt all links to the upper syntax to be compliant with the document generation.

Note

It is discouraged to have cobigen-core dependencies ar runtime, except for cobigen-core-api which definitly must be present

Plugin Activator

Each plug-in has to have an plug-in activator class implementing the interface GeneratorPluginActivator from the core-api. This class will be used to load the plug-in using the PluginRegistry as explained here. This class implements two methods:

  1. bindMerger() → returns a mapping of merge strategies and its implementation to be registered.

  2. bindTriggerInterpreter()→ returns the trigger interpreters to be provided by this plug-in.

Both methods create and register instances of mergers and trigger interpreters to be provided by the new plug-in.

Adding TriggerInterpreter

The trigger interpreter has to implement the TriggerInterpreter interface from the core. The trigger interpreter defines the type for the new plugin and creates new InputReader and new Matcher objects.

Adding InputReader

The input reader is responsible of read the input object and parse it into FreeMarker models. The input reader must be implemented for the type of the input file. If there is any existent plugin that has the same file type as input, there will be no need to add a new input reader to the new plug-in.

InputReader Interface

The interface needed to add a new input reader is defined at the core. Each new sub plug-in must implements this interface if is needed an input reader for it.

The interface implements the basic methods that an input reader must have, but if additional methods are required, the developer must add a new interface that extends the original interface InputReader.java from the core-api and implement that on the sub plug-in.

The methods to be implemented by the input reader of the new sub plugin are:

Method Return Type Description

isValidInput(Object input)

boolean

This function will be called if matching triggers or matching templates should be retrieved for a given input object.

createModel(Object input)

Map<String, Object>

This function should create the FreeMarker object model from the given input.

combinesMultipleInputObjects(Object input)

boolean

States whether the given input object combines multiple input objects to be used for generation.

getInputObjects(Object input, Charset inputCharset)

List<Object>

Will return the set of combined input objects if the given input combines multiple input objects.

getTemplateMethods(Object input)

Map<String, Object>

This method returns available template methods from the plugins as Map. If the plugin which corresponds to the input does not provide any template methods an empty Map will be returned.

getInputObjectsRecursively(Object input, Charset inputCharset)

List<Object>

Will return the set of combined input objects if the given input combines multiple input objects.

Model Constants

The Input reader will create a model for FreeMarker. A Freemarker model must have variables to use them at the .ftl template file. Refer to Java Model to see the FreeMarker model example for java input files.

Registering the Input Reader

The input reader is an object that can be retrieved using the correspondent get method of the trigger interpreter object. The trigger interpreter object is loaded at the eclipse plug-in using the load plug-in method explained here. That way, when the core needs the input reader, only needs to call that getInputReader method.

Adding Matcher

The matcher implements the MatcherInterpreter interface from the core-api. Should be implemented for providing a new input matcher. Input matcher are defined as part of a trigger and provide the ability to restrict specific inputs to a set of templates. This restriction is implemented with a MatcherType enum.

E.g JavaPlugin

private enum MatcherType {
    /** Full Qualified Name Matching */
    FQN,
    /** Package Name Matching */
    PACKAGE,
    /** Expression interpretation */
    EXPRESSION
}

Furthermore, matchers may provide several variable assignments, which might be dependent on any information of the matched input and thus should be resolvable by the defined matcher.

E.g JavaPlugin

private enum VariableType {
    /** Constant variable assignment */
    CONSTANT,
    /** Regular expression group assignment */
    REGEX
}

Adding Merger

The merger is responsible to perform merge action between new output with the existent data at the file if it already exists. Must implement the Merger interface from the core-api. The implementation of the Merge interface must override the following methods:

Method Return Type Description

getType()

String

Returns the type, this merger should handle.

merge(File base, String patch, String targetCharset)

String

Merges the patch into the base file.

Is important to know that any exception caused by the merger must throw a MergeException from the core-api to the eclipse-plugin handle it.

Changes since Eclipse / Maven 3.x

Since version 3.x the Eclipse and Maven plugins of CobiGen utilize the Java ServiceLoader mechanic to find and register plugins at runtime. To enable a new plugin to be discovered by this mechanic the following steps are needed:

  • create the file META-INF/services/com.capgemini.cobigen.api.extension.GeneratorPluginActivator containing just the full qualified name of the class implementing the GeneratorPluginActivator interface, if the plugin provides a Merger and/or a TriggerInterpreter

  • create the file META-INF/services/com.capgemini.cobigen.api.extension.TextTemplateEngine containing just the full qualified name of the class implementing the TextTemplateEngine interface, if provided by the plugin

  • include META-INF into the target bundle (i.e. the folder META-INF has to be present in the target jar file)

Example: Java Plugin

The java plugin provides both a Merger and a TriggerInterpreter. It contains therefore a com.capgemini.cobigen.api.extension.GeneratorPluginActivator file with the followong content:

com.capgemini.cobigen.javaplugin.JavaPluginActivator
This makes the JavaPluginActivator class discoverable by the ServiceLoader at runtime.
  • to properly include the plugin into the current system and use existing infrastructure, you need to add the plugin as a module in /cobigen/pom.xml (in case of a Merger/TriggerInterpreter providing plugin) and declare that as the plugin’s parent in it’s own pom.xml via

<parent>
    <groupId>com.capgemini</groupId>
    <artifactId>cobigen-parent</artifactId>
    <version>dev-SNAPSHOT</version>
</parent>

or /cobigen/cobigen-templateengines/pom.xml (in case of a Merger/TriggerInterpreter providing plugin) and declare that as the plugin’s parent in it’s own pom.xml via

<parent>
    <groupId>com.capgemini</groupId>
    <artifactId>cobigen-tempeng-parent</artifactId>
    <version>dev-SNAPSHOT</version>
</parent>

If the plugin provides both just use the /cobigen/pom.xml.

  • The dependencies of the plugin are included in the bundle

  • To make the plugin available to the Eclipse plugin it must be included into the current compositeContent.xml and compositeArtifacts.xml files. Both files are located in http://de-mucevolve02/files/cobigen/updatesite/{experimental|nightly|stable}. To do so, add an <child> entry to the <children> tag in both files and adapt the size attribute to match the new number of references. The location attribute of the new <child> tag needs to be the artifact id of the plugins pom.xml.

Example: Java Plugin

In case of the Java plugin, the entry is

<child location="cobigen-javaplugin"/>

Deployment

For the Maven Plugin

Execute mvn clean deploy from the plugins project folder. You need to configure write access to the devon nexus (e.g in the CobiGen IDE via the variables-customized script)

For the Eclipse Plugin

Depending on the kind of release you want to publish you can chose from the following maven profiles:

  • experimental is for, as the name suggests, experimental snapshot builds. In case of new plugins this is a good place to upload first drafts.

  • nightly is for periodically CI deployment.

  • stable is solely for releases.

E.g. you want an experimental release you need to follow these steps:

# Builds the Manifest and bundles the dependencies
mvn clean package bundle:bundle -Pp2Bundle
# Uses the created bundle and builds a p2 update site for it. Do NOT use clean
mvn install bundle:bundle -Pp2Bundle p2:site
# Uploades the p2 update site to the experimental repository. Do NOT use clean
mvn install -Pexperimental
You need write access to the iCSD Fileserver configured (e.g in the CobiGen IDE via the variables-customized script).
Clone this wiki locally