12. Generating Source from a Schema


Contents

12.1. Defining Template Files

12.2. Generating Source Code


 

12.1. Defining Template Files

Once a mapping schema has been defined, you can generate Java source code for your persistent classes. The mapping tool provides the flexibility to generate source code in any required format by generating source code based on a template you define. A template is defined by means of a template file that defines the format to use when generating source code for a persistent class. A template file is a text file made up of Java source code and special tags. A template file can be created or edited using any text editor.

The next section jumps directly into an example that shows the source code that is generated from a simple template. A definition of all possible template tags is then given in the section following the example.

 

12.1.1. Example

Below are the contents of a very simple template file named simple_template.tmpl that is included in the schema repository directory. This template file defines all attributes as public, declares a constructor that initializes all attributes to null, and implements get and set methods for each attribute:

package %PACKAGE_NAME%;

import com.objectmatter.bsf.*;

public class %CLASS_NAME%%EXTENDS_SUPERCLASS% {

    //attributes
    %[%ATR%public %ATR_TYPE% %ATR_NAME%;]%

    //constructor
    public %CLASS_NAME%() {
        %[%ATR_NAME% = null;]%
    }

    //attribute accessors
    %[%ATR%public %ATR_TYPE% get%ATR_NAME_CAP%() {
        return %ATR_NAME%;
    }]%

    //attribute mutators
    %[%ATR%public %ATR_TYPE% set%ATR_NAME_CAP%(%ATR_TYPE% new%ATR_NAME_CAP%) {
        %ATR_NAME% = new%ATR_NAME_CAP%;
    }]%

}

And below is an example of the source code generated by the above template file:

package vcontactdemo.engine;

import com.objectmatter.bsf.*;

public class Contact {

    //attributes
    public java.lang.Long id;
    public java.lang.String lastName;
    public java.lang.String firstName;

    //constructor
    public Contact() {
        id = null;
        lastName = null;
        firstName = null;
    }

    //attribute accessors
    public java.lang.Long getId() {
        return id;
    }
    public java.lang.String getLastName() {
        return lastName;
    }
    public java.lang.String getFirstName() {
        return firstName;
    }

    //attribute mutators
    public java.lang.Long setId(java.lang.Long newId) {
        id = newId;
    }
    public java.lang.String setLastName(java.lang.String newLastName) {
        lastName = newLastName;
    }
    public java.lang.String setFirstName(java.lang.String newFirstName) {
        firstName = newFirstName;
    }

}

 

12.1.2. Template Tags

The source code generator processes a template file by interpreting and processing all template tags, and outputting all remaining text unchanged into the generated source code file. Template tags are always capitalized words separated by underscores and surrounded with the percentage (%) sign (e.g., %PACKAGE_NAME% is a tag). There are three types of tags: Place Holders, Types, and Loops. Place Holder tags are substituted by an actual schema object name or type during source code generation. There are two types of Place Holder tags: Looped Place Holder tags, and Non-Looped Place Holder tags. Looped Place Holder tags must be placed inside a loop. For example the tag %CLASS_NAME% is a Non-Looped Place Holder tag that is replaced by the actual name of each class.

Type tags specify the type of schema object to be processed within a loop. Loop tags are used to specify that one or more statements are to be repeated for the schema object represented by a Type or Looped Place Holder tag. Loop tags delimit all text and tags that should be repeated for all the applicable schema objects. The Loop Start tag is a percentage sign followed by an open bracket (%[). The Loop End tag is a close bracket followed by percentage sign (]%). The Loop Start tag must always be followed by either a Looped Place Holder tag or a Type tag that specifies the type of schema object to be processed in the loop. Below is a table that shows all Type and Place Holder tags with a brief description of each:

Type Tags
Tag Description
%ATR% Attribute of any type
%SIMPLE_ATR% Simple attributes
%SIMPLE_ATR_TYPE_EQUAL% Simple attributes of a specific data or access type (1)
%SIMPLE_ATR_TYPE_NOT_EQUAL% Simple attributes not of a specific data or access type (1)
%RELATION_ATR% Relationship attributes
%RELATION_ATR_TYPE_EQUAL% Relationship attributes of a specific data or access type (1)
%RELATION_ATR_TYPE_NOT_EQUAL% Relationship attributes not of a specific data or access type (1)
Non-Looped Place Holder Tags
Tag Description
%PACKAGE_NAME% Name of the package
%CLASS_NAME% Name of the class
%EXTENDS_SUPERCLASS% Name of superclass prefixed by ' extends ', or blank if no superclass (2)
%ABSTRACT% Returns ' abstract' if class is abstract, else is blank (2)
%COMMENT% Allows you to put a template file comment that is not part of the source code (3)
%SUPRESS_PACKAGE_NAMES% Suppresses package names in the generated source (3)
%PRESERVED_CODE% Marks the location where existing preserved code is to be placed (4)
%PREFIX_OUTPUT_SPEC% Specifies an alternate output package name and/or class name based on a prefix (5)
%SUFFIX_OUTPUT_SPEC% Specifies an alternate output package name and/or class name based on a suffix (5)
%OID_ATR_NAME% Returns the name of the object ID attribute
Looped Place Holder Tags
Tag Description
%ATR_NAME% Attribute name
%ATR_NAME_CAP% Attribute name w/first letter capitalized
%ATR_NAME_FULLCAP% Attribute name all capitalized
%ATR_NAME_WO_PREFIX% Attribute name w/specified prefix removed (6)
%ATR_NAME_WO_SUFFIX% Attribute name w/specified suffix removed (6)
%ATR_NAME_CAP_WO_PREFIX% Attribute name w/first letter capitalized and specified prefix removed (6)
%ATR_NAME_FULLCAP_WO_PREFIX% Attribute name all capitalized and specified prefix removed (6)
%ATR_NAME_CAP_WO_SUFFIX% Attribute name w/first letter capitalized and specified suffix removed (6)
%ATR_NAME_FULLCAP_WO_SUFFIX% Attribute name all capitalized and specified suffix removed (6)
%ATR_TYPE% Attribute Java type
%ATR_GET_METHOD% Name of attribute getter method
%ATR_SET_METHOD% Name of attribute setter method
%ATR_METHOD_INDEX_NUMBER% Index number of get/set method
%ATR_TABLE_NAME% Table name attribute or class maps to
%ATR_COLUMN_NAME% Column name attribute maps to
%ATR_COL_DATA_TYPE% Data type of column attribute maps to
%SIMPLE_ATR_NAME% Simple attribute name
%SIMPLE_ATR_NAME_CAP% Simple attribute name w/first letter capitalized
%SIMPLE_ATR_NAME_FULLCAP% Simple attribute name all capitalized
%SIMPLE_ATR_NAME_WO_PREFIX% Simple attribute name w/specified prefix removed (6)
%SIMPLE_ATR_NAME_WO_SUFFIX% Simple attribute name w/specified suffix removed (6)
%SIMPLE_ATR_NAME_CAP_WO_PREFIX% Simple attribute name w/first letter capitalized and specified prefix removed (6)
%SIMPLE_ATR_NAME_FULLCAP_WO_PREFIX% Simple attribute name all capitalized and specified prefix removed (6)
%SIMPLE_ATR_NAME_CAP_WO_SUFFIX% Simple attribute name w/first letter capitalized and specified suffix removed (6)
%SIMPLE_ATR_NAME_FULLCAP_WO_SUFFIX% Simple attribute name all capitalized and specified suffix removed (6)
%SIMPLE_ATR_TYPE% Simple attribute Java type
%SIMPLE_ATR_GET_METHOD% Name of simple attribute getter method
%SIMPLE_ATR_SET_METHOD% Name of simple attribute setter method
%SIMPLE_ATR_METHOD_INDEX_NUMBER% Index number of get/set method
%SIMPLE_ATR_TABLE_NAME% Table name simple attribute or class maps to
%SIMPLE_ATR_COLUMN_NAME% Column name simple attribute maps to
%SIMPLE_ATR_COL_DATA_TYPE% Data type of column simple attribute maps to
%RELATION_ATR_NAME% Relationship attribute name
%RELATION_ATR_NAME_CAP% Relationship attribute name w/first letter capitalized
%RELATION_ATR_NAME_FULLCAP% Relationship attribute name all capitalized
%RELATION_ATR_NAME_WO_PREFIX% Relationship attribute name w/specified prefix removed (6)
%RELATION_ATR_NAME_WO_SUFFIX% Relationship attribute name w/specified suffix removed (6)
%RELATION_ATR_NAME_CAP_WO_PREFIX% Relationship attribute name w/first letter capitalized and specified prefix removed (6)
%RELATION_ATR_NAME_FULLCAP_WO_PREFIX% Relationship attribute name all capitalized and specified prefix removed (6)
%RELATION_ATR_NAME_CAP_WO_SUFFIX% Relationship attribute name w/first letter capitalized and specified suffix removed (6)
%RELATION_ATR_NAME_FULLCAP_WO_SUFFIX% Relationship attribute name all capitalized and specified suffix removed (6)
%RELATION_ATR_TYPE% Relationship attribute Java type
%RELATION_ATR_GET_METHOD% Name of relation attribute getter method
%RELATION_ATR_SET_METHOD% Name of relation attribute setter method
%RELATION_ATR_METHOD_INDEX_NUMBER% Index number of get/set method
%RELATION_ATR_TABLE_NAME% Table name relation attribute or class maps to
%RELATION_ATR_COLUMN_NAME% Column name relation attribute maps to
%RELATION_ATR_COL_DATA_TYPE% Data type of column relation attribute maps to
%REFERENCED_CLASS_NAME% Name of referenced class

Table Notes:

(1)  Type tags ending with _EQUAL or _NOT_EQUAL must be suffixed with one or more actual attribute data or access type(s) to compare against. The table below lists the possible data types for simple attributes (SIMPLE_ATR) and for relationship attributes (RELATION_ATR):

Simple Data Types
INTEGER
LONG
FLOAT
DOUBLE
BOOLEAN
STRING
DATE
BIGDECIMAL
MEMO
BLOB
OBJECT
Relationship Data Types
ALL_RELATIONS
ALL_REFERENCES
OWNED_OREFERENCE
REFERENCED_OREFERENCE
CONTAINED_OREFERENCE
OREFERENCE
OWNED_REFERENCED_INTERFACE
REFERENCED_REFERENCED_INTERFACE
CONTAINED_REFERENCED_INTERFACE
REFERENCED_INTERFACE
OWNED_REFERENCE
REFERENCED_REFERENCE
CONTAINED_REFERENCE
REFERENCE
ALL_COLLECTIONS
HOMOGENEOUS_COLLECTION
HETEROGENEOUS_COLLECTION
OWNED_OCOLLECTION
REFERENCED_OCOLLECTION
OCOLLECTION
OWNED_JAVACOLLECTION
REFERENCED_JAVACOLLECTION
JAVACOLLECTION
OWNED_ARRAY
REFERENCED_ARRAY
ARRAY
OWNED_VECTOR
REFERENCED_VECTOR
VECTOR

The JAVACOLLECTION, OWNED_JAVACOLLECTION and REFERENCED_JAVACOLLECTION tags are used with REFERENCED
COLLECTION attributes of Java data type Collection (java.util.Collection).

The OWNED_REFERENCED_INTERFACE, REFERENCED_REFERENCED_INTERFACE, CONTAINED_REFERENCED_INTERFACE and REFERENCED_INTERFACE tags are used with REFERENCE attributes of a Java type where an interface implemented by the referenced class is specified.

The access type is the method the persistence layer uses to read and set the value of an attribute. The table below lists the possible access types for attributes of all data types:

Access Types
VARIABLE_ACCESS
METHOD_ACCESS
METHOD_ACCESS_INDEXED_BY_NAME
METHOD_ACCESS_INDEXED_BY_NUMBER
METHOD_ACCESS_NOT_INDEXED

For example, the following template loop will create accessor methods for all boolean attributes:

%[%SIMPLE_ATR_TYPE_EQUAL BOOLEAN%public %SIMPLE_ATR_TYPE% is%SIMPLE_ATR_NAME_CAP%() {
    return %SIMPLE_ATR_NAME%;
}]%

For a boolean attribute named valid, the following code would be generated:

public boolean isValid() {
    return valid;
}

The loop below creates an accessor method for all relationship attributes accessed via a getter method:

%[%RELATION_ATR_TYPE_EQUAL METHOD_ACCESS%public %RELATION_ATR_TYPE% %RELATION_ATR_GET_METHOD%() {
return %RELATION_ATR_NAME%;
}]%

Multiple attribute data types can be combined using the OR logical operator, represented using a vertical bar (|). For example, the loop below will only be processed for attributes of type long, integer, and float:

%[%SIMPLE_ATR_TYPE_EQUAL LONG|INTEGER|FLOAT%public %SIMPLE_ATR_TYPE% is%SIMPLE_ATR_NAME_CAP%() {
    return %SIMPLE_ATR_NAME%;
}]%

You can also combine data and access types using OR or AND operators. The AND operator is specified using an ampersand sign (&). The loop below defines an accessor method for relationship attributes of data type ARRAY accessed via direct variable access, or of data type REFERENCE accessed via direct variable access:


%[%RELATION_ATR_TYPE_EQUAL ARRAY&VARIABLE_ACCESS|REFERENCE&VARIABLE_ACCESS%public %RELATION_ATR_TYPE% get%RELATION_ATR_NAME_WO_PREFIX my%() {
return %RELATION_ATR_NAME%;
}]%

 

(2)  These tags are substituted by strings containing a leading space. For example, notice that in the template code below the %ABSTRACT% tag is placed right after the public modifier without any separating spaces, and so is the %EXTENDS_SUPERCLASS% tag.

public%ABSTRACT% class %CLASS_NAME%%EXTENDS_SUPERCLASS% {

The above template code generates source code spaced as shown below:

public abstract class Assembly extends Item {

For classes that are not abstract and/or do not extend a superclass these tags are ignored, and no extra spaces are generated as shown below:

public class Invoice {

The %EXTENDS_SUPERCLASS% tag can also accept a default superclass name if one has not been specified in the schema. This is done by putting the superclass name in the actual tag (e.g., %EXTENDS SUPERCLASS MyDefaultBaseClass%).

 

(3)  These are special tags that do not actually get substituted by anything. The %COMMENT% tag is used to place comments in the template file that are not part of the generated source code. Below is an example of a template comment:

%COMMENT This comment is not printed in the source code%

The %SUPRESS_PACKAGE_NAMES% tag is used to suppress package qualified class names. For example, when the %SIMPLE_ATR_TYPE% tag is encountered for a string attribute, it is substituted by java.lang.String. To have the source code generator use the non-qualified class name instead, put the %SUPRESS_PACKAGE_NAMES% tag at the top of the template file.

 

(4)  Changes to the source code of existing classes can now be preserved from generation to generation by means of the %PRESERVED_CODE% tag. This tag must be placed in 2 places:

  1. In the template file to specify where the preserved source code block should be placed. See the template4.tmpl file in the samples schrepository directory.
  2. In the actual source code inside comments to delimit the preserved code. For example:

    /* PRESERVED_CODE */

    All your custom code is here, including additional (non-persistent) attributes,
    methods, static variables and methods, constructors, comments, etc.

    /* PRESERVED_CODE */

    During source code generation the mapping tool will preserve all code enclosed inside the /* PRESERVED_CODE */  block and place it in the newly generated source code at the location specified by the the %PRESERVED_CODE% tag in the template. Note that only one /* PRESERVED_CODE */ code block is allowed per class.

 

(5)  By default, source for each class is generated using the package name and class name specified in the schema. These tags allow specifying an alternate output package name and/or class name for source code generation. This is useful, for example, for generating interfaces or entity beans for the persistent classes. The %PREFIX_OUTPUT_SPEC% and %SUFFIX_OUTPUT_SPEC% tags accept two arguments. The first argument is the alternate package name. The second argument is either a prefix or suffix (depending on the tag used) used to concatenate to the persistent class name in order to come up with the alternate name. At least one of the arguments must be specified. Below are some examples of usage, based on a persistent class named com.persistent.Customer:

%SUFFIX_OUTPUT_SPEC com.interface Intf% - generates an interface named com.interface.CustomerIntf
%PREFIX_OUTPUT_SPEC com.interface Intf% - generates an interface named com.interface.IntfCustomer
%SUFFIX_OUTPUT_SPEC Intf% - generates an interface named com.persistent.CustomerIntf
%SUFFIX_OUTPUT_SPEC com.interface % - generates an interface named com.interface.Customer (note the space after the package name inside the tag)

Note that these tags are used only for the names of the directories and files created during generation. The template itself must also use the correct prefix/suffix in the class name and the alternate package name. When used, either tag must be placed on top of the template file, before all other tags (except for the COMMENT tag, which may be placed before). For an example, please see the template6.tmpl template in the schrepository directory.

 

(6)  Looped Place Holder tags ending with _PREFIX or _SUFFIX must be suffixed with the actual prefix or suffix to be removed from the attribute name. For example if a simple attribute has a letter 'f' (for field) prefixed in its name that should be removed so an accessor method is properly named, we could use the following template loop:

%[%SIMPLE_ATR%public %SIMPLE_ATR_TYPE% get%SIMPLE_ATR_NAME_WO_PREFIX f%() {
    return %SIMPLE_ATR_NAME%;
}]%

For a string attribute named fName, the following code would be generated:

public java.lang.String getName() {
    return fName;
}

 

12.1.3. Additional Examples

Below is an example of the template code used to generate a constructor that initializes all simple attributes to the values supplied as parameters to the constructor:

public %CLASS_NAME%( %[%SIMPLE_ATR_TYPE% init%SIMPLE_ATR_NAME_CAP%, ]%) {
    %[%SIMPLE_ATR_NAME% = init%SIMPLE_ATR_NAME_CAP%;]%
}

The above template code would result in the following generated code for the Location class of the vcompanydemo sample application:

public Location( long initId,
                 java.lang.String initLocationName,
                 java.lang.String initAddress,
                 ) {
    id = initId;
    locationName = initLocationName;
    address = initAddress;
}

And below is an example of template code that can be used to generate an accessor method for relationship attributes of type OReference:

%[%RELATION_ATR_TYPE_EQUAL OREFERENCE%public %REFERENCED_CLASS_NAME% get%RELATION_ATR_NAME_WO_PREFIX my%() throws BODBException {
    return (%REFERENCED_CLASS_NAME%)%RELATION_ATR_NAME%.get();
}]%

The above template code generates the code shown below for the attribute myOwner (of type OReference) defined in the Location class of the vcompanydemo sample application:

public vcompanydemo.Company getOwner() throws BODBException {
    return (vcompanydemo.Company)myOwner.get();
}

The schema repository directory contains a template file named template.tmpl which was used to generate the source code for all the persistent classes in the vcompanydemo sample application. The repository directory also contains other more complex sample template files. A listing of all included sample template files, along with a description, can be found in a README.txt file located in the schema repository directory. Please review these templates for examples of usage of other more complex options.

 

12.2. Generating Source Code

To generate source code in the mapping tool select the Generate->Source code from schema menu option to display the dialog box shown below.

mtgensourcedlg.jpg (28613 bytes)

The Available list shows all classes defined in the current application schema. Use the Add and Add All buttons to move classes from the Available list to the Selected list. You can also use the Remove and Remove All buttons to move classes from the Selected list back to the Available list.

Click the Options button to bring up the Generation Options panel of the configuration dialog box if necessary to verify or update the template file and output directory to be used when generating source code.

Once the Selected list displays the classes for which you want to generate source code click the Generate button to start the generation process. Generated source code is placed on a directory structure based on the package name under the output directory. Any final output directories that do not exist are automatically created. The generation procedure creates a separate Java source code file with extension .java   for each class selected. If multiple Java files are desired per selected class (e.g., when generating Enterprise Java Beans), this procedure may be run multiple times, each time against a different template. Any existing source code files in the destination directory with the same name as the ones being generated will be overwritten without warning. The status bar at the bottom edge of the mapping tool will inform you when the generation process has completed.

 

Next Section

Return to Table of Contents