Version 17 (modified by hblanco@…, 7 years ago) (diff)

Name changed from Autogen to Document/Development/Design/Core/Autogen?

Autogeneration of code

Abstract

The reason to provide the framework with a mechanism of code generation is clear: to ease the implementation of new modules.

Given that we have the experience of coding thousands of lines of ebox modules, we have realised that we are repeating some pieces of code again and again when creating a module. So another reason is to factor and relieve this issue.

The main idea behind this is using a xml file to describe the new module, and based on that file generating the necessary code to provide a scaffold base to work from. Let me put it this way, if we are implementing a module to manage a simple service as a dns-cache server, the coder will only need to change a few names and paths within the xml file which automagically will turn into a fully-fledged ebox module.

Requirements

The sketch of the improvements that it should fulfil is as follows:

  • generate code for autotools, automake and so forth
  • generate code to deal with menu entries
  • based on the data model we should be able to generate:
    • generate gconf schemas
    • code to deal with gconf data, such as accesors, mutators and so forth
    • code to deal with ldap data, such as accesors, mutators and so forth
    • basic views for the data model: html/javascript templates
    • controller role code to deal with the data: cgi's, base classes and so forth
  • some more...

Working mode

The working mode will be based on an iterative process over the analysis and implementation. To start off with, we will stick to realistic and not excessively ambitious goals. By our roadmap, we observe that we will have to test the code in an early stage, so we are going to be practical in the development of such a tool. Therefore, the implementation of some of the quotated features will be put off.

Components

The tool will be split into the following pieces.

XML module definition file

This is the most important piece from the user's point of view.

We will use  RELAX-NG (a schema language for XML) to both define the structure of the file and to be able to validate the user entries.

At the moment, our preferred way to create the schema files is using the non-compact version, although if any of you object and want to advocate the compact way you are welcome, but hurry up before we get more stuff done.

If you, as i am, are new to  RELAX-NG, take your time to read this  tutorial.

XML parser

Responsible to parse the XML file, validate its content and carry out the proper tasks to generate the scaffolding.

Templates

A handful of templates for the different files that will be generated.

The most likely template system to be used will be  Mason, as it has been extensively used throughout ebox.

Here we detail some the needed templates:

  • autoconf, autotools, ...
  • gconf schemas
  • perl main class module
  • cgi's
  • html mason templates

More components…

Design

schema for XML module definition file

As we said before, the configuration for the module is given by a XML file. Syntax and structure for such a file are represented by a RELAX-NG schema. Note that this is a very initial version, it is not even a draft, but it will help us to go towards an alpha version'

module.rng

<!-- vim: ts=4 sw=4 nowrap filetype=xml
-->

<grammar xmlns="http://relaxng.org/ns/structure/1.0">
        <start>
                <element name="eboxModule" >

                        <element name="moduleName">
                                <text/>
                        </element>
                        
                        <oneOrMore>
                                <element name="author">
                                        <text/>
                                </element>
                        </oneOrMore>
                        
                        <optional>
                                <element name="langDomain">
                                        <text/>
                                </element>
                        </optional>
                        
                        <optional>
                                <element name="depends">
                                        <text/>
                                </element>
                        </optional>



                        <optional>
                                <element name="dataModel">
                                
                                        <attribute name="backend">
                                                <choice>
                                                        <value>gconf</value>
                                                        <value>ldap</value>
                                                </choice>
                                        </attribute>
                                        
                                        <optional>
                                                <element name="customType">
                                                        <oneOrMore>
                                                                <element name="struct">
                                                                        <attribute name="name">
                                                                                <text/>
                                                                        </attribute>
                                                                        <oneOrMore>
                                                                                <ref name="keyDef" />
                                                                        </oneOrMore>
                                                                </element>
                                                        </oneOrMore>
                                                </element>
                                        </optional>
                                        
                                        <zeroOrMore>
                                                <ref name="keyDef" />
                                        </zeroOrMore>
                                        
                                </element>
                        </optional>
                
                </element>
        </start>

        <define name="keyDef">
        
                <element name="key">
                
                        <attribute name="name">
                                <text/>
                        </attribute>
                
                        <optional>
                                <element name="label">
                                        <text/>
                                </element>
                        </optional>
                        
                        <element name="type">
                                <text/>
                        </element>
                        
                        <zeroOrMore>
                                <element name="default">
                                        <optional>
                                                <attribute name="key">
                                                        <text/>
                                                </attribute>
                                        </optional>
                                        <text/>
                                </element>
                        </zeroOrMore>
                        
                </element>
                
        </define>


</grammar>


An example of a file following the above structure.

<!-- vim: ts=4 sw=4 nowrap filetype=xml
-->

<eboxModule>
        <moduleName>test</moduleName>
        <author>John Smith</author>
        <langDomain>ebox-test</langDomain>
        <depends>firewall</depends>
        
        <dataModel backend="gconf">
        
                <customType>
                        <struct name="admin">
                                <key name="email">
                                        <label>e-mail</label>
                                        <type>string</type>
                                </key>
                                <key name="phone">
                                        <label>phone number</label>
                                        <type>string</type>
                                </key>
                        </struct> 
                        <struct name="resolve">
                                <key name="host">
                                        <label>hostname</label>
                                        <type>string</type>
                                </key>
                                <key name="ip">
                                        <label>ip</label>
                                        <type>string</type>
                                </key>
                                <key name="contact">
                                        <type>admin</type>
                                </key>
                        </struct> 
                </customType>

                <key name="port">
                        <label>port</label>
                        <type>int</type>
                        <default>45</default>   
                </key> 
        
                <key name="updateServer">
                        <type>resolve</type>
                        <default key="host">foobar</default>
                        <default key="contact/email">foobar@baz.org</default>
                        <default key="contact/phone">7776666555</default>
                </key>
                
        </dataModel>

</eboxModule>