Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Tigerstripe Advanced Plugin Tutorial"

 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{backlink|Tigerstripe_Tutorials}}
+
{{backlink|Tigerstripe_Tutorials}}  
  
This tutorial builds upon the concepts discussed in the '''[[Tigerstripe_Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]'''. It introduces different rule types, shows how to incorporate more information into your templates and develop java helper classes to simplify template writing.
+
This tutorial builds upon the concepts discussed in the '''[[Tigerstripe Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]'''. It introduces different rule types, shows how to incorporate more information into your templates and develop java helper classes to simplify template writing.  
  
=Defining Global Rules=
+
= Defining Global Rules =
  
In the '''[[Tigerstripe_Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]''' we created a simple '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]'''. These rules are run once per '''[[Tigerstripe_Glossary#Artifact|artifact]]''' (for the the relevant Artifact Type) in the project, and produce a single file for each artifact.
+
In the '''[[Tigerstripe Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]''' we created a simple '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rule]]'''. These rules are run once per '''[[Tigerstripe Glossary#Artifact|artifact]]''' (for the the relevant Artifact Type) in the project, and produce a single file for each artifact.  
  
In some situations, you may desire or need to create a file that contains information about multiple artifacts. For example, a single XML file that contains information about all of the artifacts in a project or an HTML index page that provides links to pages about each entity. In this case you would define a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]'''.
+
In some situations, you may desire or need to create a file that contains information about multiple artifacts. For example, a single XML file that contains information about all of the artifacts in a project or an HTML index page that provides links to pages about each entity. In this case you would define a '''[[Tigerstripe Glossary#Global_Rule|Global Rule]]'''.  
  
'''[[Tigerstripe_Glossary#Global Rule|Global Rules]]''' are executed once per generation of a project. There are a few differences from '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rules]]''':
+
'''[[Tigerstripe Glossary#Global_Rule|Global Rules]]''' are executed once per generation of a project. There are a few differences from '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rules]]''': Creating a '''[[Tigerstripe Glossary#Global_Rule|Global Rule]]''' follows the same process as creating an '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rule]]''', however there is less information to enter upon creation.  
Creating a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]''' follows the same process as creating an '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]''', however there is less information to enter upon creation.  
+
  
In the following example you will create a very simplistic XML schema that has elements for each Entity in the model. Note: The validity of this schema is questionable; it is intended purely as an example of a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]'''.
+
In the following example you will create a very simplistic XML schema that has elements for each Entity in the model. Note: The validity of this schema is questionable; it is intended purely as an example of a '''[[Tigerstripe Glossary#Global_Rule|Global Rule]]'''.  
  
To create a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]''':
+
To create a '''[[Tigerstripe Glossary#Global_Rule|Global Rule]]''':  
  
1. Create a '''[[Tigerstripe_Glossary#Velocity Template|template]]''' in the ''templates'' directory of your '''[[Tigerstripe_Glossary#Tigerstripe Plugin Project|Plugin Project]]'''. Name this template ''globalTemplate.vm'' and save the template.
+
1. Create a '''[[Tigerstripe Glossary#Velocity_Template|template]]''' in the ''templates'' directory of your '''[[Tigerstripe Glossary#Tigerstripe_Plugin_Project|Plugin Project]]'''. Name this template ''globalTemplate.vm'' and save the template. The template should include the following content:  
The template should include the following content:
+
  
 
       ## This is globalTemplate.vm
 
       ## This is globalTemplate.vm
      <?xml version="1.0" encoding="UTF-8"?>
+
    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
      <schema>
+
    &lt;schema&gt;
 
       <!-- This file was generated using "globalTemplate.vm" -->
 
       <!-- This file was generated using "globalTemplate.vm" -->
      #foreach ($entity in $entities)
+
          <complexType name="$entity.Name" >
+
                <complexContent>
+
    #foreach ($entity in $entities)
                      <sequence>
+
        &lt;complexType name="$entity.Name" &gt;
      #foreach ($attribute in $entity.Fields)
+
              &lt;complexContent&gt;
                          <element name="$attribute.Name" type="$attribute.Type.Name" />
+
                    &lt;sequence&gt;
      #end
+
    #foreach ($attribute in $entity.Fields)
                      </sequence>
+
                        &lt;element name="$attribute.Name" type="$attribute.Type.Name" /&gt;
              </complexContent>
+
    #end
          </complexType>
+
                    &lt;/sequence&gt;
      #end
+
            &lt;/complexContent&gt;
      </schema>
+
        &lt;/complexType&gt;
 +
    #end
 +
    &lt;/schema&gt;
  
Take look at a few key lines in this template:
+
Take look at a few key lines in this template:  
  
* ''#foreach ($entity in $entities) ...... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each entity in the model.
+
*''#foreach ($entity in $entities) ...... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each entity in the model.  
** $entities is one of a number of possible collections.
+
**$entities is one of a number of possible collections.  
** $enumerations, $datatypes etc, contain all instances of a particular artifact type.
+
**$enumerations, $datatypes etc, contain all instances of a particular artifact type.  
** $artifacts is the complete set of artifacts in the model.
+
**$artifacts is the complete set of artifacts in the model.
  
* ''#foreach ($attribute in $entity.Fields)..... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each '''[[Tigerstripe_Glossary#Attribute|attribute]]''' defined in the entity.
+
*''#foreach ($attribute in $entity.Fields)..... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each '''[[Tigerstripe Glossary#Attribute|attribute]]''' defined in the entity.  
** '''[[Tigerstripe_Glossary# Attribute|Attributes]]''' are of type IField - more details can be found in the API documentation in the on-line Help.  
+
**'''[[Tigerstripe Glossary#_Attribute|Attributes]]''' are of type IField - more details can be found in the API documentation in the on-line Help.  
** Other useful collections are ''Literals'' for '''[[Tigerstripe_Glossary#Constant|Constants]]''' and ''Methods'' for '''[[Tigerstripe_Glossary#Method|Methods]]'''.
+
**Other useful collections are ''Literals'' for '''[[Tigerstripe Glossary#Constant|Constants]]''' and ''Methods'' for '''[[Tigerstripe Glossary#Method|Methods]]'''.  
* type="$attribute.Type.Name" - Scans the model to obtain the name of the attribute type.
+
*type="$attribute.Type.Name" - Scans the model to obtain the name of the attribute type.
  
'''Note''': You can obtain a more complete picture of the model structure by looking at the javaDoc for the Tigerstripe external API.
+
'''Note''': You can obtain a more complete picture of the model structure by looking at the javaDoc for the Tigerstripe external API.  
  
2. Create a Global rule that points to the '''[[Tigerstripe_Glossary#Velocity Template|template]]''' you created.
+
2. Create a Global rule that points to the '''[[Tigerstripe Glossary#Velocity_Template|template]]''' you created. You accomplish this in the same way you created an '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rule]]'''. Refer to '''[[Tigerstripe Simple Plugin Tutorial#Define_a_Plug-in_Rule|Define a Plug-in Rule]]''' for more information. There are actually two types of Global Rule - for this rule, select the "Simple Run Rule" from the drop-down list - this should be the default.  
You accomplish this in the same way you created an '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]'''. Refer to '''[[Tigerstripe_Simple_Plugin_Tutorial#Define a Plug-in Rule|Define a Plug-in Rule]]''' for more information. There are actually two types of Global Rule - for this rule, select the "Simple Run Rule" from the drop-down list - this should be the default.
+
  
 
3. Click '''Save''' to save your changes.  
 
3. Click '''Save''' to save your changes.  
  
The next time you generate a '''[[Tigerstripe_Glossary#Tigerstripe Model Project|Project]]''' with this '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''' enabled, you should get a schema file (schema.xsd) with content similar to the following:
+
The next time you generate a '''[[Tigerstripe Glossary#Tigerstripe_Model_Project|Project]]''' with this '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]''' enabled, you should get a schema file (schema.xsd) with content similar to the following:  
  
  <?xml version="1.0" encoding="UTF-8"?>
+
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  <schema>
+
  &lt;schema&gt;
 
  <!-- This file was generated using "globalTemplate.vm" -->
 
  <!-- This file was generated using "globalTemplate.vm" -->
    <complexType name="Order" >
+
          <complexContent>
+
                <sequence>
+
  &lt;complexType name="Order" &gt;
                    <element name="details" type="String" />
+
        &lt;complexContent&gt;
                </sequence>
+
              &lt;sequence&gt;
        </complexContent>
+
                  &lt;element name="details" type="String" /&gt;
    </complexType>
+
              &lt;/sequence&gt;
    <complexType name="Service" >
+
      &lt;/complexContent&gt;
          <complexContent>
+
  &lt;/complexType&gt;
                <sequence>
+
  &lt;complexType name="Service" &gt;
                    <element name="Counter" type="int" />
+
        &lt;complexContent&gt;
                    <element name="ServiceName" type="String" />
+
              &lt;sequence&gt;
                </sequence>
+
                  &lt;element name="Counter" type="int" /&gt;
        </complexContent>
+
                  &lt;element name="ServiceName" type="String" /&gt;
    </complexType>
+
              &lt;/sequence&gt;
  </schema>
+
      &lt;/complexContent&gt;
 +
  &lt;/complexType&gt;
 +
  &lt;/schema&gt;
  
In this example, you have two entities named, Order and Service. The Service entity has two attributes, Counter and ServiceName.
+
In this example, you have two entities named, Order and Service. The Service entity has two attributes, Counter and ServiceName.  
  
 
It is important to realize that in a real model, you will see different content in the schema file but the structure will be the same and will be repeated for each entity.  
 
It is important to realize that in a real model, you will see different content in the schema file but the structure will be the same and will be repeated for each entity.  
  
Important: '''[[Tigerstripe_Glossary#Global Rule|Global]]''', '''[[Tigerstripe_Glossary#Model Based Rule|Model]]''' and '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rules]]''' can exist in the same '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]'''. Be careful to choose unique output file names.
+
Important: '''[[Tigerstripe Glossary#Global_Rule|Global]]''', '''[[Tigerstripe Glossary#Model_Based_Rule|Model]]''' and '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rules]]''' can exist in the same '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]'''. Be careful to choose unique output file names.  
  
=Defining Model Based Rules=
+
= Defining Model Based Rules =
  
In the '''[[Tigerstripe_Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]''' we created a simple '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]'''. These rules are run once per '''[[Tigerstripe_Glossary#Artifact|artifact]]''' (for the the relevant Artifact Type) in the project, and produce a single file for each artifact.
+
As a further variant of the rules we defined above, you may desire or need to create a file that contains information about the artifacts that exist in each "model" that is referenced from your own model project. In this case you would define a '''[[Tigerstripe Glossary#Model_Based_Rule|Model Based Rule]]'''.  
  
In some situations, you may desire or need to create a file that contains information about multiple artifacts. For example, a single XML file that contains information about all of the artifacts in a project or an HTML index page that provides links to pages about each entity. In this case you would define a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]'''.
+
'''[[Tigerstripe Glossary#Model_Based_Rule|Model Based Rules]]''' are executed once per model that is found in the depndency hierachy of a project. This will include any refernced modelas an and installed modules. The rule will walk the hiearchy tree to discover transitive depndencies in the tree. There are a few differences from '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rules]]''': Creating a '''[[Tigerstripe Glossary#Model_Based_Rule|Model Based Rule]]''' follows the same process as creating an '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rule]]''', however there is less information to enter upon creation.  
  
'''[[Tigerstripe_Glossary#Global Rule|Global Rules]]''' are executed once per generation of a project. There are a few differences from '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rules]]''':
+
In the following example you will create a very simplistic XML schema that has elements for each Entity in each model in teh dependecny tree. Note: The validity of this schema is questionable; it is intended purely as an example of a '''[[Tigerstripe Glossary#Model_Based_Rule|Model Based Rule]]'''.  
Creating a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]''' follows the same process as creating an '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]''', however there is less information to enter upon creation.  
+
  
In the following example you will create a very simplistic XML schema that has elements for each Entity in the model. Note: The validity of this schema is questionable; it is intended purely as an example of a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]'''.
+
To create a '''[[Tigerstripe Glossary#Model_Based_Rule|Model Based Rule]]''':
  
To create a '''[[Tigerstripe_Glossary#Global Rule|Global Rule]]''':
+
1. Create a '''[[Tigerstripe Glossary#Velocity_Template|template]]''' in the ''templates'' directory of your '''[[Tigerstripe Glossary#Tigerstripe_Plugin_Project|Plugin Project]]'''. Name this template ''modelTemplate.vm'' and save the template. The template should include the following content:  
  
1. Create a '''[[Tigerstripe_Glossary#Velocity Template|template]]''' in the ''templates'' directory of your '''[[Tigerstripe_Glossary#Tigerstripe Plugin Project|Plugin Project]]'''. Name this template ''globalTemplate.vm'' and save the template.
+
      ## This is modelTemplate.vm
The template should include the following content:
+
    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
 +
    &lt;schema&gt;
 +
      <!-- This file was generated using "modelTemplate.vm" -->
 +
 +
 +
    #foreach ($entity in $moduleEntities)
 +
        &lt;complexType name="$entity.Name" &gt;
 +
              &lt;complexContent&gt;
 +
                    &lt;sequence&gt;
 +
    #foreach ($attribute in $entity.Fields)
 +
                        &lt;element name="$attribute.Name" type="$attribute.Type.Name" /&gt;
 +
    #end
 +
                    &lt;/sequence&gt;
 +
            &lt;/complexContent&gt;
 +
        &lt;/complexType&gt;
 +
    #end
 +
    &lt;/schema&gt;
  
      ## This is globalTemplate.vm
+
This is very similar to the globalTemplate we saw above, but there is one key difference.  
      <?xml version="1.0" encoding="UTF-8"?>
+
      <schema>
+
      <!-- This file was generated using "globalTemplate.vm" -->
+
      #foreach ($entity in $entities)
+
          <complexType name="$entity.Name" >
+
                <complexContent>
+
                      <sequence>
+
      #foreach ($attribute in $entity.Fields)
+
                          <element name="$attribute.Name" type="$attribute.Type.Name" />
+
      #end
+
                      </sequence>
+
              </complexContent>
+
          </complexType>
+
      #end
+
      </schema>
+
  
Take look at a few key lines in this template:
+
*''#foreach ($entity in $moduleEntities) ...... #end'' - The collection that is being iterated over is different! the $moduleEntities collection willbe limited to the entities in any given model in the tree.
  
* ''#foreach ($entity in $entities) ...... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each entity in the model.
+
2. When defining an output file Name for the rule, you will most likeley need to use the model Identity - something like ${modelId}.  
** $entities is one of a number of possible collections.
+
** $enumerations, $datatypes etc, contain all instances of a particular artifact type.
+
** $artifacts is the complete set of artifacts in the model.
+
  
* ''#foreach ($attribute in $entity.Fields)..... #end'' - This line defines the enclosed template elements and ensures that they are iterated for each '''[[Tigerstripe_Glossary#Attribute|attribute]]''' defined in the entity.
+
Other than that, creating a model rule is very similar to creating a global rule.  
** '''[[Tigerstripe_Glossary# Attribute|Attributes]]''' are of type IField - more details can be found in the API documentation in the on-line Help.
+
** Other useful collections are ''Literals'' for '''[[Tigerstripe_Glossary#Constant|Constants]]''' and ''Methods'' for '''[[Tigerstripe_Glossary#Method|Methods]]'''.
+
* type="$attribute.Type.Name" - Scans the model to obtain the name of the attribute type.
+
  
'''Note''': You can obtain a more complete picture of the model structure by looking at the javaDoc for the Tigerstripe external API.
+
Important: '''[[Tigerstripe Glossary#Global_Rule|Global]]''', '''[[Tigerstripe Glossary#Model_Based_Rule|Model]]''' and '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rules]]''' can exist in the same '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]'''. Be careful to choose unique output file names.  
  
2. Create a Global rule that points to the '''[[Tigerstripe_Glossary#Velocity Template|template]]''' you created.
+
= Using Java Wrappers  =
You accomplish this in the same way you created an '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]'''. Refer to '''[[Tigerstripe_Simple_Plugin_Tutorial#Define a Plug-in Rule|Define a Plug-in Rule]]''' for more information. There are actually two types of Global Rule - for this rule, select the "Simple Run Rule" from the drop-down list - this should be the default.
+
  
3. Click '''Save''' to save your changes.  
+
(You can only specify a '''[[Tigerstripe Glossary#Model_Class|Wrapper]]''' within an '''[[Tigerstripe Glossary#Artifact_Rule|Artifact Rule]]''' definition.)
  
The next time you generate a '''[[Tigerstripe_Glossary#Tigerstripe Model Project|Project]]''' with this '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''' enabled, you should get a schema file (schema.xsd) with content similar to the following:
+
A '''[[Tigerstripe Glossary#Model_Class|Wrapper]]''' is a Java class that implements the '''IArtifactWraper''' interface specified in the '''[[Tigerstripe Glossary#Tigerstripe_External_API|Tigerstripe External API]]'''. A wrapper is a set of code around a core Tigerstripe artifact that enables custom behaviour to be added to artifact. Appropriate use of a '''[[Tigerstripe Glossary#Model_Class|Wrapper]]''' can greatly simplify '''[[Tigerstripe Glossary#Velocity_Template|templates]]''' and enhance their readability.  
  
<?xml version="1.0" encoding="UTF-8"?>
+
In the ''[[Tigerstripe Glossary#Model_Class|Wrapper]]'' you define methods to manipulate the information available from the '''[[Tigerstripe Glossary#Artifact|artifact]]''', '''[[Tigerstripe Glossary#Tigerstripe_Project|project]]''' etc, or look-up additional data. Some examples of method usage within a model are:
<schema>
+
<!-- This file was generated using "globalTemplate.vm" -->
+
    <complexType name="Order" >
+
          <complexContent>
+
                <sequence>
+
                    <element name="details" type="String" />
+
                </sequence>
+
        </complexContent>
+
    </complexType>
+
    <complexType name="Service" >
+
          <complexContent>
+
                <sequence>
+
                    <element name="Counter" type="int" />
+
                    <element name="ServiceName" type="String" />
+
                </sequence>
+
        </complexContent>
+
    </complexType>
+
</schema>
+
  
In this example, you have two entities named, Order and Service. The Service entity has two attributes, Counter and ServiceName.
+
*Reformat data - You may want to translate a package name to a directory path name. For example, com.mycompany.models could become com/mycompany/models.  
 
+
*Look up data in other related '''[[Tigerstripe Glossary#Artifact|artifacts]]'''- eg If the '''[[Tigerstripe Glossary#Type|type]]''' of an '''[[Tigerstripe Glossary#Attribute|attribute]]''' is an '''[[Tigerstripe Glossary#Enumeration_Artifact|enumeration]]''', you can examine the '''Base Type''' of that '''[[Tigerstripe Glossary#Enumeration_Artifact|enumeration]]''' (ie int or String).
It is important to realize that in a real model, you will see different content in the schema file but the structure will be the same and will be repeated for each entity.  
+
*Read additional data from a configuration file in the '''[[Tigerstripe Glossary#Tigerstripe_Project|project]]''' or '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]'''.
 +
*Perform complex manipulations that would be difficult in '''[[Tigerstripe Glossary#Velocity|Velocity]]'''.
  
Important: '''[[Tigerstripe_Glossary#Global Rule|Global]]''', '''[[Tigerstripe_Glossary#Model Based Rule|Model]]''' and '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rules]]''' can exist in the same '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]'''. Be careful to choose unique output file names.
+
<br> The '''[[Tigerstripe Glossary#Artifact|artifact]]''' that is to be processed is passed to the ''[[Tigerstripe Glossary#Model_Class|Wrapper]]'' using the '''setIArtifact''' method.  
  
=Using Java Wrappers=
+
<br> To create a new '''[[Tigerstripe Glossary#Model_Class|Wrapper]]''':
  
(You can only specify a '''[[Tigerstripe_Glossary#Model Class|Wrapper]]''' within an '''[[Tigerstripe_Glossary#Artifact Rule|Artifact Rule]]''' definition.)
+
#Create a new Java Class in the src directory of your plugin project.  
 
+
#The Class must implement the '''IArtifactWrapper''' interface.  
A '''[[Tigerstripe_Glossary#Model Class|Wrapper]]''' is a Java class that implements the '''IArtifactWraper''' interface specified in the '''[[Tigerstripe_Glossary#Tigerstripe External API|Tigerstripe External API]]'''.  A wrapper is a set of code around a core Tigerstripe artifact that enables custom behaviour to be added to artifact. Appropriate use of a '''[[Tigerstripe_Glossary#Model Class|Wrapper]]''' can greatly simplify '''[[Tigerstripe_Glossary#Velocity Template|templates]]''' and enhance their readability.
+
#*For this tutorial Name your model ''EntityWrapper'' in the ''com.mycompany.plugins.wrappers'' package  
 
+
#Add the methods as outlined in the following example:
In the ''[[Tigerstripe_Glossary#Model Class|Wrapper]]'' you define methods to manipulate the information available from the '''[[Tigerstripe_Glossary#Artifact|artifact]]''', '''[[Tigerstripe_Glossary#Tigerstripe Project|project]]''' etc, or look-up additional data. Some examples of method usage within a model are:
+
 
+
* Reformat data - You may want to translate a package name to a directory path name. For example, com.mycompany.models could become com/mycompany/models.
+
* Look up data in other related '''[[Tigerstripe_Glossary#Artifact|artifacts]]'''- eg If the '''[[Tigerstripe_Glossary#Type|type]]''' of an '''[[Tigerstripe_Glossary#Attribute|attribute]]''' is an '''[[Tigerstripe_Glossary#Enumeration Artifact|enumeration]]''', you can examine the '''Base Type''' of that '''[[Tigerstripe_Glossary#Enumeration Artifact|enumeration]]''' (ie int or String).
+
* Read additional data from a configuration file in the '''[[Tigerstripe_Glossary#Tigerstripe Project|project]]''' or '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]'''.
+
* Perform complex manipulations that would be difficult in '''[[Tigerstripe_Glossary#Velocity|Velocity]]'''.
+
 
+
 
+
The '''[[Tigerstripe_Glossary#Artifact|artifact]]''' that is to be processed is passed to the ''[[Tigerstripe_Glossary#Model Class|Wrapper]]'' using the '''setIArtifact''' method.
+
 
+
 
+
To create a new '''[[Tigerstripe_Glossary#Model Class|Wrapper]]''':
+
 
+
# Create a new Java Class in the src directory of your plugin project.
+
# The Class must implement the '''IArtifactWrapper''' interface.
+
#* For this tutorial Name your model ''EntityWrapper'' in the ''com.mycompany.plugins.wrappers'' package
+
# Add the methods as outlined in the following example:
+
  
 +
<br>
  
 
  public class EntityWrapper implements IArtifactWrapper {
 
  public class EntityWrapper implements IArtifactWrapper {
    private IArtifact artifact;   
+
  private IArtifact artifact;   
    private IPluginConfig pluginConfig;
+
  private IPluginConfig pluginConfig;
    public void setIArtifact(IArtifact artifact) {
+
  public void setIArtifact(IArtifact artifact) {
        this.artifact = artifact;
+
      this.artifact = artifact;
    }
+
  }
    public void setPluginConfig(IPluginConfig pluginConfig) {
+
  public void setPluginConfig(IPluginConfig pluginConfig) {
        this.pluginConfig = pluginConfig;
+
      this.pluginConfig = pluginConfig;
    }
+
  }
    public IArtifact getArtifact(){
+
  public IArtifact getArtifact(){
        return artifact;
+
      return artifact;
    }
+
  }
    public String getName(){
+
  public String getName(){
        return getArtifact().getName()+"Value";
+
      return getArtifact().getName()+"Value";
    }
+
  }
    public String getKeyName(){
+
  public String getKeyName(){
        return getArtifact().getName()+"Key";
+
      return getArtifact().getName()+"Key";
    }
+
  }
    public String getOutPath(){
+
  public String getOutPath(){
        String packageName = getArtifact().getPackage();
+
      String packageName = getArtifact().getPackage();
        String path = packageName.replaceAll("\\.", "/");
+
      String path = packageName.replaceAll("\\.", "/");
        return path;
+
      return path;
    }
+
  }
}
+
  
Note: You will need to "import" the '''IArtifactWrapper''', '''IPluginConfig''' and '''IArtifact''' interfaces for the '''[[Tigerstripe_Glossary#Tigerstripe External API|Tigerstripe External API]]'''.
+
}
  
In this example, you will specify the type of your artifact to be '''IArtifact'''. This allows the model to be used for any artifact type. In many cases however, you may wish to create a more specific type of artifact, such as '''IManagedEntityArtifact'''. This allows access to methods on a particular artifact type. It is also possible to create a generic wrapper and inherit from that wrapper for each specific artifact type.
+
Note: You will need to "import" the '''IArtifactWrapper''', '''IPluginConfig''' and '''IArtifact''' interfaces for the '''[[Tigerstripe Glossary#Tigerstripe_External_API|Tigerstripe External API]]'''.  
  
Note that through the '''pluginConfig''' object that is passed, you can gain access to project properties.
+
In this example, you will specify the type of your artifact to be '''IArtifact'''. This allows the model to be used for any artifact type. In many cases however, you may wish to create a more specific type of artifact, such as '''IManagedEntityArtifact'''. This allows access to methods on a particular artifact type. It is also possible to create a generic wrapper and inherit from that wrapper for each specific artifact type.  
  
Having created your wrapper, you will need to refer to it in a '''[[Tigerstripe_Glossary#Velocity Template|template]]''' and then set up a rule to pass the model to the template.
+
Note that through the '''pluginConfig''' object that is passed, you can gain access to project properties.  
  
To reference your wrapperin a '''[[Tigerstripe_Glossary#Velocity Template|template]]''':
+
Having created your wrapper, you will need to refer to it in a '''[[Tigerstripe Glossary#Velocity_Template|template]]''' and then set up a rule to pass the model to the template.
  
1. Create your '''[[Tigerstripe_Glossary#Velocity Template|template]]'''. This procedure is the same as previously outlined, but within the '''[[Tigerstripe_Glossary#Velocity Template|template]]''' you will make reference to methods on the '''[[Tigerstripe_Glossary#Model Class|wrapper]]'''.
+
To reference your wrapperin a '''[[Tigerstripe Glossary#Velocity_Template|template]]''':
 +
 
 +
1. Create your '''[[Tigerstripe Glossary#Velocity_Template|template]]'''. This procedure is the same as previously outlined, but within the '''[[Tigerstripe Glossary#Velocity_Template|template]]''' you will make reference to methods on the '''[[Tigerstripe Glossary#Model_Class|wrapper]]'''.  
  
 
  ## This is wrapperTemplate.vm
 
  ## This is wrapperTemplate.vm
Line 232: Line 194:
 
  // is not the same as the model Name ($wrapper.Name).
 
  // is not the same as the model Name ($wrapper.Name).
 
  public interface ${wrapper.Name} {
 
  public interface ${wrapper.Name} {
    public String get${wrapper.KeyName};
+
  public String get${wrapper.KeyName};
 
  }  
 
  }  
  
 +
<br> 2. Create a new rule as described in the '''[[Tigerstripe Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]'''. However, in the '''Wrapper Class''' field, browse to the '''[[Tigerstripe Glossary#Model_Class|Wrapper Class]]''' that you created above. In the '''Wrapper Class Name''' text box, enter the name by which the wrapper will be referred to within your template.
  
2. Create a new rule as described in the '''[[Tigerstripe_Tutorials#Tigerstripe_Simple_Plugin_Tutorial|Simple Plugin Tutorial]]'''. However, in the '''Wrapper Class''' field, browse to the '''[[Tigerstripe_Glossary#Model Class|Wrapper Class]]''' that you created above. In the '''Wrapper Class Name''' text box, enter the name by which the wrapper will be referred to within your template.
+
*In this tutorial, name your Wrapper class ''wrapper ''. Hence the use of ''$wrapper '' in the above template example.  
* In this tutorial, name your Wrapper class ''wrapper ''. Hence the use of ''$wrapper '' in the above template example.
+
 
*Note: The Output File definition can contain references to wrapper methods by using the ${model.xxx} syntax.
 
*Note: The Output File definition can contain references to wrapper methods by using the ${model.xxx} syntax.
  
3. Click '''Save''' to save your plug-in project.
+
3. Click '''Save''' to save your plug-in project. 4. '''Generate''' against your Tigerstripe project.  
4. '''Generate''' against your Tigerstripe project.
+
  
The generated file for the ''Order'' entity will be in a directory based on it's package name, and will have the name ''OrderValue.out''. It will contain a method called ''getOrderKey''.
+
The generated file for the ''Order'' entity will be in a directory based on it's package name, and will have the name ''OrderValue.out''. It will contain a method called ''getOrderKey''.  
  
You could have easily achieved this result by using template functions, but as your processing becomes more and more complex, wrappers will become an essential part of your plug-ins.
+
You could have easily achieved this result by using template functions, but as your processing becomes more and more complex, wrappers will become an essential part of your plug-ins.  
  
Note: IArtifactWrapper replaces the old IArtifactModel which had the same basic behaviour.
+
Note: IArtifactWrapper replaces the old IArtifactModel which had the same basic behaviour.  
  
=Artifact Filters=
+
= Artifact Filters =
  
(This feature only applies to Artifact Rules)
+
(This feature only applies to Artifact Rules)  
  
Sometimes you may need to run through a subset of '''[[Tigerstripe_Glossary#Artifact|artifacts]]''' of a given Artifact type. Rather than code a rule into your '''[[Tigerstripe_Glossary#Velocity Template|template]]''', you can specify an '''[[Tigerstripe_Glossary#Artifact Filter|Artifact Filter]]''' that will limit the artifacts that are processed in the '''[[Tigerstripe_Glossary#Velocity Template|template]]'''. This will keep your '''[[Tigerstripe_Glossary#Velocity Template|templates]]''' simple and easy to understand.
+
Sometimes you may need to run through a subset of '''[[Tigerstripe Glossary#Artifact|artifacts]]''' of a given Artifact type. Rather than code a rule into your '''[[Tigerstripe Glossary#Velocity_Template|template]]''', you can specify an '''[[Tigerstripe Glossary#Artifact_Filter|Artifact Filter]]''' that will limit the artifacts that are processed in the '''[[Tigerstripe Glossary#Velocity_Template|template]]'''. This will keep your '''[[Tigerstripe Glossary#Velocity_Template|templates]]''' simple and easy to understand.  
  
'''[[Tigerstripe_Glossary#Artifact Filter|Artifact Filters]]''' are defined in a similar manner to '''[[Tigerstripe_Glossary#Model Class|Models]'''. That is, '''[[Tigerstripe_Glossary#Artifact Filter|Artifact Filters]]''' are Java classes in the ''src'' directory of your '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''' that implement the '''IArtifactModel''' interface. The '''[[Tigerstripe_Glossary#Artifact Filter|filter]]''' needs to implement a single ''select'' method and any artifact that returns a result of ''true'', is passed to the template engine for further processing.
+
'''[[Tigerstripe Glossary#Artifact_Filter|Artifact Filters]]''' are defined in a similar manner to '''[[Tigerstripe_Glossary#Model Class|Models]'''. That is, '''[[Tigerstripe Glossary#Artifact_Filter|Artifact Filters]]''' are Java classes in the ''src'' directory of your '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]''' that implement the '''IArtifactModel''' interface. The '''[[Tigerstripe Glossary#Artifact_Filter|filter]]''' needs to implement a single ''select'' method and any artifact that returns a result of ''true'', is passed to the template engine for further processing.  
  
In the following '''[[Tigerstripe_Glossary#Artifact Filter|filter]]''', only '''[[Tigerstripe_Glossary#Artifact|artifacts]]''' that have a '''[[Tigerstripe_Glossary#Stereotype|Stereotype]]''' of name Version are accepted and all other '''[[Tigerstripe_Glossary#Artifact|artifacts]]''' are rejected. For a detailed discussion of '''[[Tigerstripe_Glossary#Stereotype|Stereotypes]]''' see the Advanced Stereotypes to Tigerstripe Models tutorial.
+
In the following '''[[Tigerstripe Glossary#Artifact_Filter|filter]]''', only '''[[Tigerstripe Glossary#Artifact|artifacts]]''' that have a '''[[Tigerstripe Glossary#Stereotype|Stereotype]]''' of name Version are accepted and all other '''[[Tigerstripe Glossary#Artifact|artifacts]]''' are rejected. For a detailed discussion of '''[[Tigerstripe Glossary#Stereotype|Stereotypes]]''' see the Advanced Stereotypes to Tigerstripe Models tutorial.  
  
 +
<br>
  
 
  public class VersionFilter implements IArtifactFilter {
 
  public class VersionFilter implements IArtifactFilter {
    public boolean select(IArtifact artifact) {     
+
  public boolean select(IArtifact artifact) {     
        IextStereotypeInstance[] stereos = artifact.getStereotypeInstances();
+
      IextStereotypeInstance[] stereos = artifact.getStereotypeInstances();
        for (IextStereotypeInstance instance: stereos){
+
      for (IextStereotypeInstance instance: stereos){
            if (instance.getName().equals("Version")){
+
          if (instance.getName().equals("Version")){
                return true;
+
              return true;
            }
+
          }
        }
+
      }
        return false;
+
      return false;
    }
+
  }
 
  }
 
  }
  
Once you have defined a '''[[Tigerstripe_Glossary#Artifact Filter|filter]]''', you can apply that '''[[Tigerstripe_Glossary#Artifact Filter|filter]]''' to an '''[[Tigerstripe_Glossary#Artifact Rule|artifact rule]]''' by clicking on '''Browse''' next to the '''Artifact Filter''' field in the '''[[Tigerstripe_Glossary#Plugin Project Descriptor|plugin descriptor]]''' editor, '''Rules''' tab.  
+
Once you have defined a '''[[Tigerstripe Glossary#Artifact_Filter|filter]]''', you can apply that '''[[Tigerstripe Glossary#Artifact_Filter|filter]]''' to an '''[[Tigerstripe Glossary#Artifact_Rule|artifact rule]]''' by clicking on '''Browse''' next to the '''Artifact Filter''' field in the '''[[Tigerstripe Glossary#Plugin_Project_Descriptor|plugin descriptor]]''' editor, '''Rules''' tab.  
  
Note: Remember to deploy your plug-in when you change a rule definition.
+
Note: Remember to deploy your plug-in when you change a rule definition.  
  
=Velocity Context Definitions=
+
= Velocity Context Definitions =
  
Another way to simplify '''[[Tigerstripe_Glossary#Velocity Template|templates]]''' is to create a Utility class. A Utility class contains commonly used methods; a typical case might be a set of String manipulation utilities. These could be third party utilities or your own.
+
Another way to simplify '''[[Tigerstripe Glossary#Velocity_Template|templates]]''' is to create a Utility class. A Utility class contains commonly used methods; a typical case might be a set of String manipulation utilities. These could be third party utilities or your own.  
  
To write your own utility:
+
To write your own utility:  
  
1. Create a class in the ''src'' directory of your '''[[Tigerstripe_Glossary#Plugin Project|plugin project]]'''.
+
1. Create a class in the ''src'' directory of your '''[[Tigerstripe Glossary#Plugin_Project|plugin project]]'''.  
* For this tutorial, name your class 'MyUtils'.
+
 
2. Add methods as appropriate to your class. You can add as many methods as you like, but for this example you will create a single method (shown below):
+
*For this tutorial, name your class 'MyUtils'.
 +
 
 +
2. Add methods as appropriate to your class. You can add as many methods as you like, but for this example you will create a single method (shown below):  
  
 
  public class MyUtils {   
 
  public class MyUtils {   
    public String capitalize(String inString){
+
  public String capitalize(String inString){
        return inString.substring(0,1).toUpperCase() +
+
      return inString.substring(0,1).toUpperCase() +
              inString.substring(1);     
+
            inString.substring(1);     
    }
+
  }
 
  }
 
  }
  
3. Add Utility classes to your '''[[Tigerstripe_Glossary#Rule|rule]]''' by adding them to the list of '''[[Tigerstripe_Glossary#Velocity Context Definitions|Velocity Context Definitions]]'''. Each definition (either your own or a reference to a .jar containing utilities) must have an entry with a ''name'' and a ''path'' . The name is used in the '''[[Tigerstripe_Glossary#Velocity Template|template]]''' to identify the specific utility class.
+
3. Add Utility classes to your '''[[Tigerstripe Glossary#Rule|rule]]''' by adding them to the list of '''[[Tigerstripe Glossary#Velocity_Context_Definitions|Velocity Context Definitions]]'''. Each definition (either your own or a reference to a .jar containing utilities) must have an entry with a ''name'' and a ''path'' . The name is used in the '''[[Tigerstripe Glossary#Velocity_Template|template]]''' to identify the specific utility class.  
 +
 
 +
In your '''[[Tigerstripe Glossary#Velocity_Template|template]]''', you can then use these methods with the ''$utilName.methodName(arg)'' syntax. For example, using the utility as defined above, which has been added with the name ''myUtils'':
  
In your '''[[Tigerstripe_Glossary#Velocity Template|template]]''', you can then use these methods with the ''$utilName.methodName(arg)'' syntax. For example, using the utility as defined above, which has been added with the name ''myUtils'':
 
 
  public $attribute.Type.Name get${myUtils.capitalize($attribute.Name)}();
 
  public $attribute.Type.Name get${myUtils.capitalize($attribute.Name)}();
  
Note: In this case the ${ } syntax for '''[[Tigerstripe_Glossary#Velocity|Velocity]]''' can help when your utility function is adjacent to other text.
+
Note: In this case the ${ } syntax for '''[[Tigerstripe Glossary#Velocity|Velocity]]''' can help when your utility function is adjacent to other text.  
 +
 
 +
If you call a method that does not exist, '''[[Tigerstripe Glossary#Velocity|Velocity]]''' will simply leave the reference in place. For example, if you mistype the above function name and run your '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]''', you may find a line (such as the one outlined below) in your output file:
  
If you call a method that does not exist, '''[[Tigerstripe_Glossary#Velocity|Velocity]]''' will simply leave the reference in place. For example, if you mistype the above function name and run your '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''', you may find a line (such as the one outlined below) in your output file:
 
 
  public String get${myUtils.capitulate(Details)}();
 
  public String get${myUtils.capitulate(Details)}();
  
=Velocity Macros=
+
= Logging and reporting statuses  =
  
'''[[Tigerstripe_Glossary#Velocity|Velocity]]''' supports the use of '''Velocimacros''' to simplify repetitive '''[[Tigerstripe_Glossary#Velocity Template|template]]''' functions. You can find out more about these macros on the Velocity website.
+
''org.eclipse.tigerstripe.workbench.plugins.PluginLog'' class provides ability to inform end user about generation details. You can use ''PluginLog.log*'' methods to log a message into the plugin specific log file. To display a message into Generate Result dialog box your should use ''PluginLog.reportStatus(IStatus)'' method.  
  
'''Velocimacros''' are added to a '''[[Tigerstripe_Glossary#Rule|rule]]''' definition in a very similar manner to'''[[Tigerstripe_Glossary#Velocity Context Defintion|Velocity Context Defintions]]'''. Simply navigate to the '''Velocity Macro''' section of the rule editor and click on "Add".
+
private static string PLUGIN_ID = "plugin.id"
 +
public class MyUtils { 
 +
  public String convert(String input) {
 +
      PluginLog.log(LogLevel.DEBUG, "converting " + input);
 +
      try {
 +
        return doConversion(input);
 +
      } catch (Exception e) {
 +
        Pluginlog.reportStatus(new Status(IStatus.ERROR, PLUGIN_ID, "error during conversion", e));
 +
      }
 +
      return null;   
 +
  }
 +
}
 +
 
 +
= Velocity Macros  =
 +
 
 +
'''[[Tigerstripe Glossary#Velocity|Velocity]]''' supports the use of '''Velocimacros''' to simplify repetitive '''[[Tigerstripe Glossary#Velocity_Template|template]]''' functions. You can find out more about these macros on the Velocity website.
 +
 
 +
'''Velocimacros''' are added to a '''[[Tigerstripe Glossary#Rule|rule]]''' definition in a very similar manner to'''[[Tigerstripe Glossary#Velocity_Context_Defintion|Velocity Context Defintions]]'''. Simply navigate to the '''Velocity Macro''' section of the rule editor and click on "Add".
 +
 
 +
Note: '''[[Tigerstripe Glossary#Tigerstripe|Tigerstripe]]''' does not support the definition of "''in-line'' macros.
 +
 
 +
= Relationship between Rules, Templates , Velocity macros, and Velocity context definitions.  =
 +
 
 +
The basic scenario is that, when a rule runs a set of objects are passed to velocity which renders the output, as described in the template specified for that rule.
 +
 
 +
The set of Java objects that are passed to velocity is the "context".
 +
 
 +
A rule *always* sends a fixed set of java objects to velocity - these are described in the section titled "Default Velocity Context Definitions" in the miscellany tutorial. Looking at this, you can see that the default context contains things such as the $project, $pluginConfig, and $artifact (for an artifact rule). There are the objects that you will use in a template.
 +
 
 +
The template only knows about those objects which the rule passes to it, and can only operate over those items.
 +
 
 +
By specifying additional "Velocity Context Entries" in a rule, you can increase the set of objects which the template can access. This is most often used for passing utility programs in that will be used for formatting data, or access external data.
 +
 
 +
As an example you might create a java utility class called MyUtils that reads an external xml file and makes the data available through some static methods such as getMyData(). By adding the class MyUtils to the list of Velocity Context Definitions in the rule, and giving it the name of "myUtils", in your template you can use $myUtils.MyData to execute the method and thus access your xml data.
 +
 
 +
Velocity Macros are a built-in velocity feature that can be used for writing a common function in the template. For example in a template that is generating java, you might have a fixed way of outputting comments - ie in a /*.....*/ block. This format requires that the text is surrounded by the right comment syntax , is at a fixed indent, the line is truncated to a given length and so on.Rather than write this code at every point you want a comment, you could write a macro that takes some text and renders the text in the right way. Every time you have a comment you simply call the macro, passing it the text of the comment as an argument.
 +
 
 +
<br>
 +
 
 +
= Runnable Rules  =
 +
 
 +
In addition to template based rules, it is possible to create "Runnable" rules for each type of rule (Global, Model Artifact). A Runnable rule passes all control to a java class that is specified in the rule defintion.
 +
 
 +
The java Class must implement the Interface IRunnableWrapper, that specifies just two methods - run and setContext. Tigerstripe will call the setContext method first, and passes in a map containing all of the context entries that are included in the Velocity context, plus a few extra items that can be used/should be respected by the rule implementation. The RunnableWrapper must contain ALL of the logic required to write files and items such as the "Suppress empty files" and "Overwrite Files" settings in the rule definition.
 +
 
 +
A typical implementation will create a local copy of the context that is set by the call to setContext, and then will access the context entries by key - the keys are the same strings that are referenced in the velocity context, and are available in the IRule Interface. So for example, a set of Datatypes can be accessed using&nbsp;:
 +
 
 +
dataTypes = (Collection&lt;IDatatypeArtifact&gt;)context.get(IRule.ALLDATATYPES);
 +
 
 +
Runnable rules give you a lot more flexibility in stucturing very complex plugins, but they do place extra onus on the implementation. You can mix teaplet and runnables in the same plugin and the selection of the type of rule is entirely a design decision.
  
Note: '''[[Tigerstripe_Glossary#Tigerstripe|Tigerstripe]]''' does not support the definition of "''in-line'' macros.
 
  
=Relationship between Rules, Templates , Velocity macros, and Velocity context definitions.=
 
 
The basic scenario is that, when a rule runs a set of objects are passed to velocity which renders the output, as described in the template specified for that rule.
 
 
The set of  Java objects that are passed to velocity is the "context".
 
 
A rule *always* sends a fixed set of java objects to velocity - these are described in the section titled "Default Velocity Context Definitions" in the miscellany tutorial. Looking at this, you can see that the default context contains things such as the $project, $pluginConfig, and $artifact (for an artifact rule). There are the objects that you will use in a template.
 
 
The template only knows about those objects which the rule passes to it, and can only operate over those items.
 
 
By specifying additional "Velocity Context Entries" in a rule, you can increase the set of objects which the template can access. This is most often used for passing utility programs in that will    be used for formatting data, or access external data.
 
 
As an example you might create a java utility class called MyUtils that reads an external xml file and makes the data available through some static methods such as getMyData(). By adding the class MyUtils to the list of Velocity Context Definitions in the rule, and giving it the name of "myUtils", in your template you can use $myUtils.MyData to execute the method and thus access your xml data.
 
 
Velocity Macros are a built-in velocity feature that can be used for  writing a common function in the template. For example in a template that is generating java, you might have a fixed way of outputting comments - ie in a /*.....*/ block.  This format requires that the text is surrounded by the right comment  syntax , is at a fixed indent, the line is truncated to a given length and so on.Rather than write this code at every point you want a comment, you could write a macro that takes some text and renders the text in the right way. Every time you have a comment you simply call the macro, passing it the text of the comment as an argument.
 
 
  
 +
<br>
  
=Plug-in Reports=
+
= Plug-in Reports =
  
Each time you click '''Generate''' in a '''[[Tigerstripe_Glossary#Tigerstripe Project|Tigerstripe Project]]''', you can obtain a '''[[Tigerstripe_Glossary#Tigerstripe Report|Tigerstripe Report]]''' in the ''target'' directory of your project. You can enable or disable this feature though the '''Advanced'' pane of the '''[[Tigerstripe_Glossary#Tigerstripe Project Descriptor|Tigerstripe Project Descriptor]]''' (tigerstripe.xml) Editor.
+
Each time you click '''Generate'''in a'''''<i>[[Tigerstripe Glossary#Tigerstripe_Project|Tigerstripe Project]]''', you can obtain a '''[[Tigerstripe Glossary#Tigerstripe_Report|Tigerstripe Report]]'''in the'''</i>'''target''directory of your project. You can enable or disable this feature though the'''''<i>Advanced</i> pane of the '''[[Tigerstripe Glossary#Tigerstripe_Project_Descriptor|Tigerstripe Project Descriptor]]''' (tigerstripe.xml) Editor.  
  
If you enable this feature, the '''[[Tigerstripe_Glossary#Tigerstripe Report|Tigerstripe Report]]''' will appear as TigerstripeReport.xml, and will include (in addition to other information about the project) a section for each '''[[Tigerstripe_Glossary#Rule|Rule]]'''. These reports can be useful at runtime to determine what has been handled, filtered, and generated. An example extract from a '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''' with a single '''[[Tigerstripe_Glossary#Rule|Rule]]''' is shown below:
+
If you enable this feature, the '''[[Tigerstripe Glossary#Tigerstripe_Report|Tigerstripe Report]]''' will appear as TigerstripeReport.xml, and will include (in addition to other information about the project) a section for each '''[[Tigerstripe Glossary#Rule|Rule]]'''. These reports can be useful at runtime to determine what has been handled, filtered, and generated. An example extract from a '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]''' with a single '''[[Tigerstripe Glossary#Rule|Rule]]''' is shown below:  
  
  <pluginReports>
+
  &lt;pluginReports&gt;
    <pluginReport    group  = ""
+
  &lt;pluginReport    group  = ""
                      id      = "SimplePluginProject()"
+
                    id      = "SimplePluginProject()"
                      version = "" >
+
                    version = "" &gt;
            <property directoryName = "default" />
+
          &lt;property directoryName = "default" /&gt;
            <property flag = "false" />
+
          &lt;property flag = "false" /&gt;
            <childReports>
+
          &lt;childReports&gt;
                <childReport
+
              &lt;childReport
                    ruleName = "modelRule"
+
                  ruleName = "modelRule"
                    ruleType = "Artifact Model Run Rule"  >
+
                  ruleType = "Artifact Model Run Rule"  &gt;
                    <matchedArtifacts>
+
                  &lt;matchedArtifacts&gt;
                        <matchedArtifact name = "com.mycompany.Order"/>
+
                      &lt;matchedArtifact name = "com.mycompany.Order"/&gt;
                        <matchedArtifact name = "com.mycompany.Service"/>
+
                      &lt;matchedArtifact name = "com.mycompany.Service"/&gt;
                    </matchedArtifacts>    
+
                  &lt;/matchedArtifacts&gt;    
                    <generatedFiles>
+
                  &lt;generatedFiles&gt;
                        <file name = "com/mycompany/OrderValue.out"/>
+
                      &lt;file name = "com/mycompany/OrderValue.out"/&gt;
                        <file name = "com/mycompany/ServiceValue.out"/>
+
                      &lt;file name = "com/mycompany/ServiceValue.out"/&gt;
                    </generatedFiles>
+
                  &lt;/generatedFiles&gt;
                </childReport>
+
              &lt;/childReport&gt;
            </childReports>
+
          &lt;/childReports&gt;
            </pluginReport>
+
          &lt;/pluginReport&gt;
    </pluginReports>
+
  &lt;/pluginReports&gt;
  
In this example, the initial section display information about the '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]''', and the value of the '''[[Tigerstripe_Glossary#Global Properties|Global Properties]]''' that have been set for this '''[[Tigerstripe_Glossary#Tigerstripe Project|project]]'''. As a result, a '''childReport'' is created for each '''[[Tigerstripe_Glossary#Rule|Rule]]''' in the '''[[Tigerstripe_Glossary#Tigerstripe Plugin|plugin]]'''.
+
In this example, the initial section display information about the '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]''', and the value of the'''''<i>[[Tigerstripe Glossary#Global_Properties|Global Properties]]'''that have been set for this '''[[Tigerstripe Glossary#Tigerstripe_Project|project]]'''. As a result, a '''childReport</i> is created for each '''[[Tigerstripe Glossary#Rule|Rule]]''' in the '''[[Tigerstripe Glossary#Tigerstripe_Plugin|plugin]]'''.  
  
* <matchedArtifacts> lists the qualified name for the '''[[Tigerstripe_Glossary#Artifact|artifacts]]''' that were passed to this '''[[Tigerstripe_Glossary#Rule|rule]]'''based on their Artifact Type and passed any defined '''[[Tigerstripe_Glossary#Artifact Filter|filter]]'''.
+
*&lt;matchedArtifacts&gt; lists the qualified name for the '''[[Tigerstripe Glossary#Artifact|artifacts]]''' that were passed to this '''[[Tigerstripe Glossary#Rule|rule]]'''based on their Artifact Type and passed any defined '''[[Tigerstripe Glossary#Artifact_Filter|filter]]'''.  
* <generatedFiles> lists the files generated relative to the output directory for your '''[[Tigerstripe_Glossary#Tigerstripe Project|project]]'''.
+
*&lt;generatedFiles&gt; lists the files generated relative to the output directory for your '''[[Tigerstripe Glossary#Tigerstripe_Project|project]]'''.
  
Note : This description is not complete and there will be additional information in the report.
+
Note&nbsp;: This description is not complete and there will be additional information in the report.

Latest revision as of 06:21, 17 June 2013

< To: Tigerstripe_Tutorials

This tutorial builds upon the concepts discussed in the Simple Plugin Tutorial. It introduces different rule types, shows how to incorporate more information into your templates and develop java helper classes to simplify template writing.

Defining Global Rules

In the Simple Plugin Tutorial we created a simple Artifact Rule. These rules are run once per artifact (for the the relevant Artifact Type) in the project, and produce a single file for each artifact.

In some situations, you may desire or need to create a file that contains information about multiple artifacts. For example, a single XML file that contains information about all of the artifacts in a project or an HTML index page that provides links to pages about each entity. In this case you would define a Global Rule.

Global Rules are executed once per generation of a project. There are a few differences from Artifact Rules: Creating a Global Rule follows the same process as creating an Artifact Rule, however there is less information to enter upon creation.

In the following example you will create a very simplistic XML schema that has elements for each Entity in the model. Note: The validity of this schema is questionable; it is intended purely as an example of a Global Rule.

To create a Global Rule:

1. Create a template in the templates directory of your Plugin Project. Name this template globalTemplate.vm and save the template. The template should include the following content:

     ## This is globalTemplate.vm
   <?xml version="1.0" encoding="UTF-8"?>
   <schema>


   #foreach ($entity in $entities)
       <complexType name="$entity.Name" >
             <complexContent>
                   <sequence>
   #foreach ($attribute in $entity.Fields)
                       <element name="$attribute.Name" type="$attribute.Type.Name" />
   #end
                   </sequence>
           </complexContent>
       </complexType>
   #end
   </schema>

Take look at a few key lines in this template:

  • #foreach ($entity in $entities) ...... #end - This line defines the enclosed template elements and ensures that they are iterated for each entity in the model.
    • $entities is one of a number of possible collections.
    • $enumerations, $datatypes etc, contain all instances of a particular artifact type.
    • $artifacts is the complete set of artifacts in the model.
  • #foreach ($attribute in $entity.Fields)..... #end - This line defines the enclosed template elements and ensures that they are iterated for each attribute defined in the entity.
    • Attributes are of type IField - more details can be found in the API documentation in the on-line Help.
    • Other useful collections are Literals for Constants and Methods for Methods.
  • type="$attribute.Type.Name" - Scans the model to obtain the name of the attribute type.

Note: You can obtain a more complete picture of the model structure by looking at the javaDoc for the Tigerstripe external API.

2. Create a Global rule that points to the template you created. You accomplish this in the same way you created an Artifact Rule. Refer to Define a Plug-in Rule for more information. There are actually two types of Global Rule - for this rule, select the "Simple Run Rule" from the drop-down list - this should be the default.

3. Click Save to save your changes.

The next time you generate a Project with this plugin enabled, you should get a schema file (schema.xsd) with content similar to the following:

<?xml version="1.0" encoding="UTF-8"?>
<schema>


 <complexType name="Order" >
       <complexContent>
             <sequence>
                 <element name="details" type="String" />
             </sequence>
     </complexContent>
 </complexType>
 <complexType name="Service" >
       <complexContent>
             <sequence>
                 <element name="Counter" type="int" />
                 <element name="ServiceName" type="String" />
             </sequence>
     </complexContent>
 </complexType>
</schema>

In this example, you have two entities named, Order and Service. The Service entity has two attributes, Counter and ServiceName.

It is important to realize that in a real model, you will see different content in the schema file but the structure will be the same and will be repeated for each entity.

Important: Global, Model and Artifact Rules can exist in the same plugin. Be careful to choose unique output file names.

Defining Model Based Rules

As a further variant of the rules we defined above, you may desire or need to create a file that contains information about the artifacts that exist in each "model" that is referenced from your own model project. In this case you would define a Model Based Rule.

Model Based Rules are executed once per model that is found in the depndency hierachy of a project. This will include any refernced modelas an and installed modules. The rule will walk the hiearchy tree to discover transitive depndencies in the tree. There are a few differences from Artifact Rules: Creating a Model Based Rule follows the same process as creating an Artifact Rule, however there is less information to enter upon creation.

In the following example you will create a very simplistic XML schema that has elements for each Entity in each model in teh dependecny tree. Note: The validity of this schema is questionable; it is intended purely as an example of a Model Based Rule.

To create a Model Based Rule:

1. Create a template in the templates directory of your Plugin Project. Name this template modelTemplate.vm and save the template. The template should include the following content:

     ## This is modelTemplate.vm
   <?xml version="1.0" encoding="UTF-8"?>
   <schema>


   #foreach ($entity in $moduleEntities)
       <complexType name="$entity.Name" >
             <complexContent>
                   <sequence>
   #foreach ($attribute in $entity.Fields)
                       <element name="$attribute.Name" type="$attribute.Type.Name" />
   #end
                   </sequence>
           </complexContent>
       </complexType>
   #end
   </schema>

This is very similar to the globalTemplate we saw above, but there is one key difference.

  • #foreach ($entity in $moduleEntities) ...... #end - The collection that is being iterated over is different! the $moduleEntities collection willbe limited to the entities in any given model in the tree.

2. When defining an output file Name for the rule, you will most likeley need to use the model Identity - something like ${modelId}.

Other than that, creating a model rule is very similar to creating a global rule.

Important: Global, Model and Artifact Rules can exist in the same plugin. Be careful to choose unique output file names.

Using Java Wrappers

(You can only specify a Wrapper within an Artifact Rule definition.)

A Wrapper is a Java class that implements the IArtifactWraper interface specified in the Tigerstripe External API. A wrapper is a set of code around a core Tigerstripe artifact that enables custom behaviour to be added to artifact. Appropriate use of a Wrapper can greatly simplify templates and enhance their readability.

In the Wrapper you define methods to manipulate the information available from the artifact, project etc, or look-up additional data. Some examples of method usage within a model are:

  • Reformat data - You may want to translate a package name to a directory path name. For example, com.mycompany.models could become com/mycompany/models.
  • Look up data in other related artifacts- eg If the type of an attribute is an enumeration, you can examine the Base Type of that enumeration (ie int or String).
  • Read additional data from a configuration file in the project or plugin.
  • Perform complex manipulations that would be difficult in Velocity.


The artifact that is to be processed is passed to the Wrapper using the setIArtifact method.


To create a new Wrapper:

  1. Create a new Java Class in the src directory of your plugin project.
  2. The Class must implement the IArtifactWrapper interface.
    • For this tutorial Name your model EntityWrapper in the com.mycompany.plugins.wrappers package
  3. Add the methods as outlined in the following example:


public class EntityWrapper implements IArtifactWrapper {
 private IArtifact artifact;  
 private IPluginConfig pluginConfig;
 public void setIArtifact(IArtifact artifact) {
     this.artifact = artifact;
 }
 public void setPluginConfig(IPluginConfig pluginConfig) {
     this.pluginConfig = pluginConfig;
 }
 public IArtifact getArtifact(){
     return artifact;
 }
 public String getName(){
     return getArtifact().getName()+"Value";
 }
 public String getKeyName(){
     return getArtifact().getName()+"Key";
 }
 public String getOutPath(){
     String packageName = getArtifact().getPackage();
     String path = packageName.replaceAll("\\.", "/");
     return path;
 }

}

Note: You will need to "import" the IArtifactWrapper, IPluginConfig and IArtifact interfaces for the Tigerstripe External API.

In this example, you will specify the type of your artifact to be IArtifact. This allows the model to be used for any artifact type. In many cases however, you may wish to create a more specific type of artifact, such as IManagedEntityArtifact. This allows access to methods on a particular artifact type. It is also possible to create a generic wrapper and inherit from that wrapper for each specific artifact type.

Note that through the pluginConfig object that is passed, you can gain access to project properties.

Having created your wrapper, you will need to refer to it in a template and then set up a rule to pass the model to the template.

To reference your wrapperin a template:

1. Create your template. This procedure is the same as previously outlined, but within the template you will make reference to methods on the wrapper.

## This is wrapperTemplate.vm
##
// This file was generated using $templateName.
##
// In this case the artifact Name ($artifact.Name) ,
// is not the same as the model Name ($wrapper.Name).
public interface ${wrapper.Name} {
 public String get${wrapper.KeyName};
} 


2. Create a new rule as described in the Simple Plugin Tutorial. However, in the Wrapper Class field, browse to the Wrapper Class that you created above. In the Wrapper Class Name text box, enter the name by which the wrapper will be referred to within your template.

  • In this tutorial, name your Wrapper class wrapper . Hence the use of $wrapper in the above template example.
  • Note: The Output File definition can contain references to wrapper methods by using the ${model.xxx} syntax.

3. Click Save to save your plug-in project. 4. Generate against your Tigerstripe project.

The generated file for the Order entity will be in a directory based on it's package name, and will have the name OrderValue.out. It will contain a method called getOrderKey.

You could have easily achieved this result by using template functions, but as your processing becomes more and more complex, wrappers will become an essential part of your plug-ins.

Note: IArtifactWrapper replaces the old IArtifactModel which had the same basic behaviour.

Artifact Filters

(This feature only applies to Artifact Rules)

Sometimes you may need to run through a subset of artifacts of a given Artifact type. Rather than code a rule into your template, you can specify an Artifact Filter that will limit the artifacts that are processed in the template. This will keep your templates simple and easy to understand.

Artifact Filters are defined in a similar manner to [[Tigerstripe_Glossary#Model Class|Models]. That is, Artifact Filters are Java classes in the src directory of your plugin that implement the IArtifactModel interface. The filter needs to implement a single select method and any artifact that returns a result of true, is passed to the template engine for further processing.

In the following filter, only artifacts that have a Stereotype of name Version are accepted and all other artifacts are rejected. For a detailed discussion of Stereotypes see the Advanced Stereotypes to Tigerstripe Models tutorial.


public class VersionFilter implements IArtifactFilter {
 public boolean select(IArtifact artifact) {    
     IextStereotypeInstance[] stereos = artifact.getStereotypeInstances();
     for (IextStereotypeInstance instance: stereos){
         if (instance.getName().equals("Version")){
             return true;
         }
     }
     return false;
 }
}

Once you have defined a filter, you can apply that filter to an artifact rule by clicking on Browse next to the Artifact Filter field in the plugin descriptor editor, Rules tab.

Note: Remember to deploy your plug-in when you change a rule definition.

Velocity Context Definitions

Another way to simplify templates is to create a Utility class. A Utility class contains commonly used methods; a typical case might be a set of String manipulation utilities. These could be third party utilities or your own.

To write your own utility:

1. Create a class in the src directory of your plugin project.

  • For this tutorial, name your class 'MyUtils'.

2. Add methods as appropriate to your class. You can add as many methods as you like, but for this example you will create a single method (shown below):

public class MyUtils {  
 public String capitalize(String inString){
     return inString.substring(0,1).toUpperCase() +
            inString.substring(1);    
 }
}

3. Add Utility classes to your rule by adding them to the list of Velocity Context Definitions. Each definition (either your own or a reference to a .jar containing utilities) must have an entry with a name and a path . The name is used in the template to identify the specific utility class.

In your template, you can then use these methods with the $utilName.methodName(arg) syntax. For example, using the utility as defined above, which has been added with the name myUtils:

public $attribute.Type.Name get${myUtils.capitalize($attribute.Name)}();

Note: In this case the ${ } syntax for Velocity can help when your utility function is adjacent to other text.

If you call a method that does not exist, Velocity will simply leave the reference in place. For example, if you mistype the above function name and run your plugin, you may find a line (such as the one outlined below) in your output file:

public String get${myUtils.capitulate(Details)}();

Logging and reporting statuses

org.eclipse.tigerstripe.workbench.plugins.PluginLog class provides ability to inform end user about generation details. You can use PluginLog.log* methods to log a message into the plugin specific log file. To display a message into Generate Result dialog box your should use PluginLog.reportStatus(IStatus) method.

private static string PLUGIN_ID = "plugin.id"
public class MyUtils {  
 public String convert(String input) {
     PluginLog.log(LogLevel.DEBUG, "converting " + input);
     try {
        return doConversion(input);
     } catch (Exception e) {
        Pluginlog.reportStatus(new Status(IStatus.ERROR, PLUGIN_ID, "error during conversion", e));
     }
     return null;    
 }
}

Velocity Macros

Velocity supports the use of Velocimacros to simplify repetitive template functions. You can find out more about these macros on the Velocity website.

Velocimacros are added to a rule definition in a very similar manner toVelocity Context Defintions. Simply navigate to the Velocity Macro section of the rule editor and click on "Add".

Note: Tigerstripe does not support the definition of "in-line macros.

Relationship between Rules, Templates , Velocity macros, and Velocity context definitions.

The basic scenario is that, when a rule runs a set of objects are passed to velocity which renders the output, as described in the template specified for that rule.

The set of Java objects that are passed to velocity is the "context".

A rule *always* sends a fixed set of java objects to velocity - these are described in the section titled "Default Velocity Context Definitions" in the miscellany tutorial. Looking at this, you can see that the default context contains things such as the $project, $pluginConfig, and $artifact (for an artifact rule). There are the objects that you will use in a template.

The template only knows about those objects which the rule passes to it, and can only operate over those items.

By specifying additional "Velocity Context Entries" in a rule, you can increase the set of objects which the template can access. This is most often used for passing utility programs in that will be used for formatting data, or access external data.

As an example you might create a java utility class called MyUtils that reads an external xml file and makes the data available through some static methods such as getMyData(). By adding the class MyUtils to the list of Velocity Context Definitions in the rule, and giving it the name of "myUtils", in your template you can use $myUtils.MyData to execute the method and thus access your xml data.

Velocity Macros are a built-in velocity feature that can be used for writing a common function in the template. For example in a template that is generating java, you might have a fixed way of outputting comments - ie in a /*.....*/ block. This format requires that the text is surrounded by the right comment syntax , is at a fixed indent, the line is truncated to a given length and so on.Rather than write this code at every point you want a comment, you could write a macro that takes some text and renders the text in the right way. Every time you have a comment you simply call the macro, passing it the text of the comment as an argument.


Runnable Rules

In addition to template based rules, it is possible to create "Runnable" rules for each type of rule (Global, Model Artifact). A Runnable rule passes all control to a java class that is specified in the rule defintion.

The java Class must implement the Interface IRunnableWrapper, that specifies just two methods - run and setContext. Tigerstripe will call the setContext method first, and passes in a map containing all of the context entries that are included in the Velocity context, plus a few extra items that can be used/should be respected by the rule implementation. The RunnableWrapper must contain ALL of the logic required to write files and items such as the "Suppress empty files" and "Overwrite Files" settings in the rule definition.

A typical implementation will create a local copy of the context that is set by the call to setContext, and then will access the context entries by key - the keys are the same strings that are referenced in the velocity context, and are available in the IRule Interface. So for example, a set of Datatypes can be accessed using :

dataTypes = (Collection<IDatatypeArtifact>)context.get(IRule.ALLDATATYPES);

Runnable rules give you a lot more flexibility in stucturing very complex plugins, but they do place extra onus on the implementation. You can mix teaplet and runnables in the same plugin and the selection of the type of rule is entirely a design decision.



Plug-in Reports

Each time you click Generate'in aTigerstripe Project, you can obtain a Tigerstripe Reportin thetargetdirectory of your project. You can enable or disable this feature though theAdvanced pane of the Tigerstripe Project Descriptor (tigerstripe.xml) Editor.

If you enable this feature, the Tigerstripe Report will appear as TigerstripeReport.xml, and will include (in addition to other information about the project) a section for each Rule. These reports can be useful at runtime to determine what has been handled, filtered, and generated. An example extract from a plugin with a single Rule is shown below:

<pluginReports>
  <pluginReport    group   = ""
                   id      = "SimplePluginProject()"
                   version = "" >
         <property directoryName = "default" />
         <property flag = "false" />
         <childReports>
             <childReport
                 ruleName = "modelRule"
                 ruleType = "Artifact Model Run Rule"  >
                 <matchedArtifacts>
                     <matchedArtifact name = "com.mycompany.Order"/>
                     <matchedArtifact name = "com.mycompany.Service"/>
                 </matchedArtifacts>    
                 <generatedFiles>
                     <file name = "com/mycompany/OrderValue.out"/>
                     <file name = "com/mycompany/ServiceValue.out"/>
                 </generatedFiles>
             </childReport>
         </childReports>
         </pluginReport>
 </pluginReports>

In this example, the initial section display information about the plugin', and the value of theGlobal Propertiesthat have been set for this project. As a result, a childReport is created for each Rule in the plugin.

  • <matchedArtifacts> lists the qualified name for the artifacts that were passed to this rulebased on their Artifact Type and passed any defined filter.
  • <generatedFiles> lists the files generated relative to the output directory for your project.

Note : This description is not complete and there will be additional information in the report.

Back to the top