Recipe12.3.Generating Message-Handling Stub Code


Recipe 12.3. Generating Message-Handling Stub Code

Problem

You want to generate the skeleton of your message handlers.

Solution

The following stylesheet creates a simple skeleton that takes a process name and generates stub code:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">       <xsl:output method="text"/>       <!-- Specifies which process to generate handlers for -->   <xsl:param name="process"/>   <!-- Specifies which message to generate handlers for. A special value of %ALL%         signifies all messages -->   <xsl:param name="message" select=" '%ALL%' "/>           <!-- The directory where -->   <xsl:variable name="message-dir" select=" 'messages' "/>   <xsl:variable name="directory-sep" select=" '/' "/>   <xsl:variable name="include-ext" select=" '.h' "/>          <xsl:template match="MessageRepository">     <xsl:choose>       <xsl:when test="$message='%ALL%'"  >           <xsl:apply-templates                select="Messages/Message[Receivers/ProcessRef = $process]"/>       </xsl:when>       <xsl:otherwise>         <xsl:apply-templates               select="Messages/Message[Receivers/ProcessRef = $process and                                        Name=$message]"/>       </xsl:otherwise>     </xsl:choose>   </xsl:template>            <xsl:template match="Message">     <xsl:document href="{concat(Name,'.h')}">       <xsl:call-template name="makeHeader"/>     </xsl:document>     <xsl:document href="{concat(Name,'.cpp')}">       <xsl:call-template name="makeSource"/>     </xsl:document>     </xsl:template>       <xsl:template name="makeHeader"> #ifndef <xsl:value-of select="Name"/>_h #define <xsl:value-of select="Name"/>_h     #include &lt;transport/MessageHandler.h&gt;     //Forward Declarations class <xsl:value-of select="DataTypeName"/> ; /*!TODO:  Insert addition forward declarations here.*/        class <xsl:value-of select="Name"/> : public MessageHandler { public:     <xsl:value-of select="Name"/>(const <xsl:value-of          select="DataTypeName"/>&amp; data) ;     bool process( ) ; private:         const <xsl:value-of select="DataTypeName"/>&amp; m_Data ; } ;     #endif   </xsl:template>        <xsl:template name="makeSource"> #include &lt;messages/<xsl:value-of select="Name"/>.h&gt;     /*!TODO:  Insert addition includes here.*/        <xsl:value-of select="Name"/>::<xsl:value-of select="Name"/>(const      <xsl:value-of select="DataTypeName"/>&amp; data)   : m_Data(data) { }     bool <xsl:value-of select="Name"/>::process( ) {   /*!TODO:  Insert message handler code here. */   return true;  }   </xsl:template>      </xsl:stylesheet>

This stylesheet generates a header and a source file for each message it processes, as shown in Example 12-1 and Example 12-2.

Example 12-1. AddStockOrder.h
#ifndef ADD_STOCK_ORDER_h #define ADD_STOCK_ORDER_h     #include <transport/MessageHandler.h>     //Forward Declarations class AddStockOrderData ; /*!TODO:  Insert addition forward declarations here.*/        class ADD_STOCK_ORDER : public MessageHandler { public:     ADD_STOCK_ORDER(const AddStockOrderData& data) ;     bool process( ) ; private:         const AddStockOrderData& m_Data ; } ;     #endif

Example 12-2. AddStockOrder.cpp
#include <messages/ADD_STOCK_ORDER.h>     /*!TODO:  Insert addition includes here.*/        ADD_STOCK_ORDER::ADD_STOCK_ORDER(const AddStockOrderData& data)   : m_Data(data) { }     bool ADD_STOCK_ORDER::process( ) {   /*!TODO:  Insert message handler code here. */   return true;  }

Discussion

Much of what developers do is repetitive in structure but unique in substance. In other words, we write a lot of boilerplate code that gets specialized based on the particular context. Performing any sort of repetitive work leads to boredom; boredom leads to distraction; and distraction results in bugs. Generating the repetitive parts of your code lets you concentrate on the important parts.

Tools that generate code with TODO sections are often called wizards. This message handler wizard is a very basic example of this genre. Some commercially available wizards generate the structure of entire applications. It is not clear whether XSLT can scale to create wizards of that magnitude. However, for simple kinds of stub generators for which the input is XML, XSLT is preferable to other languages, including Perl. Many Perl fanatics disagree with this statement because they view XML processing as just another form of text processing (and we all know Perl is the undisputed king of text-processing languages). However, a strong argument can be made that XML processing is not text processing, but the processing of trees that contain text nodes. As such, XSLT facilities transform trees more nimbly than Perl does. Nevertheless, Perl and XSLT can team up to create a best-of-both-worlds approach, as shown in Chapter 14. Chapter 14 also presents an extension to XSLT that removes the verbosity that gets in the way of pure XSLT-based generators.




XSLT Cookbook
XSLT Cookbook: Solutions and Examples for XML and XSLT Developers, 2nd Edition
ISBN: 0596009747
EAN: 2147483647
Year: 2003
Pages: 208
Authors: Sal Mangano

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net