Overview Show in Table of Contents

EGG is a development tool for fast and easy realization of XML to plain-text transformations. Where plain-text encompasses every data-format that is not binary, especially source-code or XML-documents. Egg is similar to XSLT, Velocity or JSP but emphasises source-code generation in a model-driven, generative development-process. Runs on Windows or Unix with Java.

EGG is worth a try, if you think that ...

EGG is made especially for ...

EGG is easy, if you know ...

Basically, you can think of EGG as something like an XSLT-processor that transforms XML-input into plain-text output based on a transformation-stylesheet. With EGG this transformation is defined in an EGG-template, that contains the plain-text patterns for the resulting output and the logic for reading and transforming the XML-input.

You can write your transformation logic in Java and all plain-text patterns just as they should look like in the generator-output. You define the control-flow of your generator as a sequence of statements in an imperative way and not rule-based as in XSLT.

EGG reads your generator-template and converts it into a java-class. Then, EGG compiles this generator-class and produces a simple startup-script for your generator. Run this startup-script with a XML-file as input to perform your 'xml-to-text' transformation and to produce your concrete plain-text output.

Download Show in Table of Contents

Download the latest EGG release at 'sourceforge.net'.

Installation Show in Table of Contents

Let's suppose you extracted the distribution into the <egg-dir> folder. Now, edit 'egg.bat' or 'egg.sh' in the '<egg-dir>/bin' folder and set variables

For easy usage, attach the '.egg' file-extension within your file-explorer to 'egg.bat' or 'egg.sh'.

Please note, EGG needs a java-compiler. Thus, you need a Java-JDK (version 1.2 or above). A JRE isn't enough.

That's all.

Running Demos Show in Table of Contents

Just run 'make-demos.{bat | sh}' in the 'demo' folder and follow the hints in 'demo/demos.txt'.

Distribution Show in Table of Contents

The EGG distribution has the following directory-structure:

License Show in Table of Contents

This distribution is free to use with respect to the GNU Lesser General Public License (LGPL, see 'license.txt'). This basically means, that you can use EGG free of charge in private and comercial projects. At your own risk, of course.

Platforms Show in Table of Contents

EGG runs on Windows or Unix with Java JDK-1.2 and above.

It was tested on Windows 98/NT/2000/XP. Windows 98 is known to make some trouble, when using the batch-startup scripts for EGG and the generated generators. For Windows 98, you need to have sufficient memory for the DOS environment-variables. Furthermore the error-checking does not always work, if EGG is called without parameters.

There was only a little testing on UNIX-systems. A Suse-Linux and some UNIX-shells on Windows, e. g. MinGW's 'MSYS' and Cygwin's 'bash'.

If you run into troubles, feel free to send a bug-report.

Future Plans Show in Table of Contents

'Hello World'-Example Show in Table of Contents

The 'Hello World'-Example uses the common programming task of generating Java-beans. A bean-generator (BeanGenerator.egg) is introduced with this example. It reads a definition for Java-beans (beans.xml) and writes the corresponding Java-classes with getter- and setter-methods for the bean-properties (PersonBean.java and AddressBean.java).

You can run EGG with this template to generate your bean-generator. Then, run the bean-generator with the 'beans.xml' as input-file to produce the Java-beans.

In the next section the development of this example is shown, step by step.

Development-Process Show in Table of Contents

The motivation for building generators is very often the wish to separate content from presentation. In the context of code generation, this means decoupling business- or application-specific requirements from technical design decisions, and to allow to separately maintain both.

The process used for developing egg-templates is bottom-up, starting from a source-code prototype. It follows four steps:

  1. Prototype-Creation: As the first step, an example of how the generated output is to look like is created. Then, this generator-output prototype is tested in the target environment, until it works as desired.

  2. AT-Analysis: In the output prototype, the application-specific code (A-Code) is identified and distinguished from the implementation-specific code, that is required for technical reasons (T-Code).

  3. Pattern-Definition: The application-specific A-Code and the technically-driven T-Code are exported to two files, and redundancies are eliminated. The A-Code locations are parameterized in the remaining T-Code. The resulting parameters are summarized in an XML document. Thus, the parameter names from the T-Code reappear as attribute names in the XML document, in order to create the reference to the input.

  4. Transformation-Programming: In this step, the pattern definitions are tied to the desired XML node matched using path expressions. Furthermore, the ordering of the generator output is defined. Moreover, the transformation logic for XML content that is eventually required for the generator output is added, and the output files are specified.

Prototype-Creation Show in Table of Contents

Suppose you want to store application-data in Java-beans. For example, you want to model person-data with first-, lastname and the person's age and you want your bean-implementation look like the following code-snippet.

/**
 * Stores name and age of a person. 
 */ 
class PersonBean {
 
    // property-constants
    public final String FIRSTNAME_PROPERTY = "FirstName";
    public final String LASTNAME_PROPERTY = "LastName";
    public final String AGE_PROPERTY = "Age";
    public final String ISALIVE_PROPERTY = "IsAlive";
 
    // bean-properties
    private String mFirstName;
    private String mLastName;
    private int mAge;
    private boolean mIsAlive;
 
    /**
     * Getter for 'FirstName'-property.
     */
    public String getFirstName() {
        return mFirstName;
    }
 
    /**
     * Setter for 'FirstName'-property.
     */
    public void setFirstName(String pFirstName) {
        mFirstName = pFirstName;
    }
 
    // ... other getter/setter ...
 
} // endof class 'PersonBean'
Figure-1: Example of a 'Person'-bean (PersonBean.java)

AT-Analysis Show in Table of Contents

After writing a prototype, which serves as a blueprint for the generated code, the AT-analysis comes next. In the next figure, all the application-specific text-strings (A-Code) are marked green. The other non-marked code remains as technically-driven implementation-pattern (T-Code).

/**
 * Stores name and age of a person. 
 */ 
class PersonBean {
 
    // property-constants
    public final String FIRSTNAME_PROPERTY = "FirstName";
    public final String LASTNAME_PROPERTY = "LastName";
    public final String AGE_PROPERTY = "Age";
    public final String ISALIVE_PROPERTY = "IsAlive";
 
    // bean-properties
    private String mFirstName;
    private String mLastName;
    private int mAge;
    private boolean mIsAlive;
 
    /**
     * Getter for 'FirstName'-property.
     */
    public String getFirstName() {
        return mFirstName;
    }
 
    /**
     * Setter for 'FirstName'-property.
     */
    public void setFirstName(String pFirstName) {
        mFirstName = pFirstName;
    }
    // ... other getter/setter ...
} // endof class 'PersonBean'
Figure-2: AT-Analysis of the 'Person'-bean (PersonBean.java)

Pattern-Definition Show in Table of Contents

With EGG you separate the application-specific information in your source-code from the technically driven implementation-patterns. This is done by writing all application-specific information into an XML-file and put the technically-driven implementaion-patterns into an egg-template. This is shown in the next two figures.

The XML element- and attribute-names that reappear as pattern-variables in the T-Code are marked with blue-color. Please note the <UpperProp> pattern-variable, which is not given in the XML-file directly, since it can derived be drived from the <UpperProp> variable.

Please also note, that the green A-Code form the previous figure-2 could be condensed to just ten green-parts in the next figure, solely by removing redundant occurrences. Thus, the other properties and the other bean could be added very quickly.

<?xml version="1.0" encoding="ISO-8859-1"?>
<Beans>
    <Bean Name="Person" Comment="Stores name and age of a person.">
        <Property Name="FirstName" Type="String"  />
        <Property Name="LastName"  Type="String"  />
        <Property Name="Age"       Type="int"     />
        <Property Name="IsAlive"   Type="boolean" />
    </Bean>
    <Bean Name="Address" Comment="Stores a street-address in city of a country.">
        <Property Name="Street"  Type="String" />
        <Property Name="Zip"     Type="int"    />
        <Property Name="City"    Type="String" />
        <Property Name="Country" Type="String" />
    </Bean>
</Beans>
Figure-3: Application-specific information of the beans (beans.xml)

And just like the A-Code in the XML-file are condensed to one occurrence, the same is true for the T-Code as well. Each pattern that is used in the prototype in figure-2 serveral times, needs only to be stated once, when listing the technically-driven information as in the next figure-4.

/**
 * <Comment>
 */
class <Bean>Bean {
 
    // property-constants
    public final String <UpperProp>_PROPERTY = "<Prop>";
 
    // bean-properties
    private <Type> m<Prop>;
 
 
    /**
     * Getter for '<Prop>'-property.
     */
    public <Type> get<Prop>() {
        return m<Prop>;
    }
 
    /**
     * Setter for '<Prop>'-property.
     */
    public void set<Prop>(<Type> p<Prop>) {
        m<Prop> = p<Prop>;
    }
} // endof class '<Bean>Bean'
Figure-4: Technically-driven information of the 'Person'-bean

Transformation-Programming Show in Table of Contents

The last step in building an EGG-template is to include the transformation-logic, that merges the XML-input with the parameters of the code-pattern.

The next figure-5 shows the complete EGG-template that accomplishes this task. You can run EGG with this template to generate your bean-generator. Then, run the bean-generator with the 'beans.xml' as input-file to produce the Java-beans.

It shows the addition of the EGG-statements for the parameterized prototype from figure-4. The '.generator' and '.apply' statements define output patterns. The syntax is similar to a Java method definition. In the parameter list of the pattern definition the XML nodes from the input are matched using path expressions (starting with a slash '/'). For each matching XML node the pattern-body is applied. That means, the statements in the pattern-body are executed sequentially line by line. Statements starting with a dot ('.') define the transformation-logic. All other statements, the lines without a dot ('.') at the beginning, are output-statements. Those output-statements have no special syntax. They are just that text that comes from the parameterized prototype, without any change. For a complete description of the EGG-syntax, please refer the user-documentation 'egg.pdf' (in German) and 'egg-eng.pdf' (in English). You find figures with the syntax-defnition in Backus-Naur-From (BNF) throughout the document.

In order to derive an EGG-template from the parameterized prototype, the only thing that is to do, is to add the statements for the transformation-logic. I.e., the parameterized prototype is just expanded by inserting EGG-Statements, there is no other rewriting necessary. This is speeding up generator-development rapidly. The following figure-5 shows the parameterized prototype of figure-4, with transformation logic already added.

.generator BeanGenerator ( Node Bean = </Beans/Bean> ) {
    .String Comment = </Comment>;
    .File outputFile = "gen/" + <Bean> + "Bean.java";
    /**
     * <Comment>
     */
    class <Bean>Bean {
 
    	// property-constants
    .apply PropertyConst ( Node Prop = </Property> ) {
        .String UpperProp = <Prop>.toString().toUpperCase();
        public final static String <UpperProp>_PROPERTY = "<Prop>";
    .}
 
    	// bean-properties
    .apply PropertyDef ( Node Prop = </Property> ) {
        .String Type = </Type>;
        private <Type> m<Prop>;
    .}
    .apply GetterSetter ( Node Prop = </Property> ) {
        .String Type = </Type>;
 
        /** 
         * Getter for '<Prop>'-property.
         */
        public <Type> get<Prop>() {
            return m<Prop>;
        }
 
        /** 
         * Setter for '<Prop>'-property.
         */
        public void set<Prop>(<Type> p<Prop>) {
            m<Prop> = p<Prop>;
        }
 
    .}
    } // endof class '<Bean>Bean'
.} // BeanGenerator
Figure-5: Code-pattern with additional transformation logic (BeanGenerator.egg)

References Show in Table of Contents

The EGG-project was initiated about five years ago. Since then, EGG was successively refined to real project needs and has proven useful in serveral private and business development-projects. E. g. an insurance-portal project (www.makler-extranet.de, www.vkb-extranet.de) that was presented at the symposium 'Modellierung 2002' and a content-management project serving the websites www.allianz.com, www.allianzgroup.com and f1.allianz.com.