<xsl:stylesheet xmlns:src="http://www.sdml.info/srcML/src" xmlns:cpp="http://www.sdml.info/srcML/cpp" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xw="http://www.pnp-software.com/XWeaver" xmlns:xd="http://www.pnp-software.com/XSLTdoc" xmlns:util="http://www.pnp-software.com/util" xmlns:ax="http://control.ee.ethz.ch/XWeaver/AspectX" version="2.0" exclude-result-prefixes="xsl">

  
  <xd:doc type="stylesheet">
    
<xd:short>AspectX Weaver</xd:short>
    
<xd:detail>This stylesheet weaves the annotated base code. 
    There is a rule for every possible combination of the following elements:
      
<ul>
        
<li>srcML element</li>
        
<li>advice type</li>
        
<li>codeModifier type (subelement of advice)</li>
      
</ul>

    Every combination is handled by one single XSL file, which is included here. The
    filename of this XSL file is constructed as follows:

      
<p><code>"srcML element name"_"advice type"_"code modifier type".xsl</code></p>

    e.g. "function_begin_codeFragment.xsl" is the fileame for the combinatiion of the
    follwing elements:
      
<ul><li>function srcML element</li>
      
<li>begin advice</li>
      
<li>code fragment codeModifier</li></ul>
    
</xd:detail>
    
<xd:cvsId>$Id: axw.xsl 138 2005-07-27 09:14:07Z ibirrer $</xd:cvsId>
    
<xd:author>ibirrer</xd:author>
    
<xd:copyright>2004, P&amp;P Software GmbH</xd:copyright>
  
</xd:doc>


  
<!-- Preserve whitespaces -->
  
<xsl:preserve-space elements="*" />
  
  
<xsl:include href="util.xsl" />
  
  
<xsl:variable name="inputFileUri" select="base-uri(/)" />
  
  
  <xd:doc>
    If set to true, intermediate woven results are saved in the temp directory.
  
</xd:doc>

  
<xsl:param name="saveTempWovenFiles" select="'false'" />
  
  
  <xd:doc>
    The default indentation that should be used for the weaving process.
    Use &amp;#x9; for tabs, &amp;#160; for spaces.
    
<xd:param name="defaultIndentation" type="string" />
  
</xd:doc>

  
<xsl:param name="defaultIndentation"><xsl:text>        </xsl:text></xsl:param>
  
  
  <xd:doc>
    
<xd:short>Deciding if a file should be woven or not.</xd:short>
    
<xd:detail>If the XML source file does not contain any annotation (advice elements), it
    is copied to the output without any changes.
    If the XML source file contains one or more advice elements, it is woven by calling the 'weaveFile'
    template.
</xd:detail>
  
</xd:doc>

  
<xsl:template match="/">
    
<xsl:choose>
      
<xsl:when test="//ax:advice">
        
<xsl:call-template name="weaveFile">
          
<xsl:with-param name="file" select="." />
        
</xsl:call-template>
        
<xsl:variable name="wovenFileName" select="util:getFile(base-uri())" />
        
<xsl:message>Weaving done for file: <xsl:value-of select="$wovenFileName" /></xsl:message>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:variable name="wovenFileName" select="util:getFile(base-uri())" />
        
<xsl:message>No weaving done for file: <xsl:value-of select="$wovenFileName" /></xsl:message>
        
<xsl:copy-of select="." />
      
</xsl:otherwise>
    
</xsl:choose>    
  
</xsl:template>
  
  
  <xd:doc>This template ensures that all XML comments are deleted</xd:doc>

  
<xsl:template match="comment()" mode="weaving" />

  
  <xd:doc>
    
<xd:short>Weaves a srmML file.</xd:short>
    
<xd:detail>
    This template can be called recursively by itself. It applies the weaving rules
    to the argument 
<code>$file</code>, as long as there are advice elements left in it. If no more advices are
    found, the woven file is sent to the output (using 
<code>xsl:copy-of</code>).</xd:detail>
    
<xd:param name="file" type="node-set">A srcML file.</xd:param>
  
</xd:doc>

  
<xsl:template name="weaveFile">
    
<xsl:param name="file" />
    
<xsl:choose>
      
<xsl:when test="$file//ax:advice">
        
<xsl:if test="$saveTempWovenFiles = 'true'">
          
<xsl:variable name="tmpFile" select="concat(substring-before($inputFileUri, '.xml'), '_',count($file//ax:advice), '.xml')" />
          
<xsl:result-document href="{$tmpFile}">
            
<xsl:copy-of select="$file" />
          
</xsl:result-document>
        
</xsl:if>
        
        
<xsl:call-template name="weaveFile">
          
<xsl:with-param name="file">
            
<xsl:apply-templates select="$file" mode="weaving" />
          
</xsl:with-param>
        
</xsl:call-template>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:copy-of select="$file" />
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:template>

  
  <xd:doc>
    Default template for annotated code. 
    If no weaver rule is defined for any 
    annotated srcML, this template is called, 
    aborts the program and outputs an error message.
  
</xd:doc>

  
<xsl:template match="*[ax:advice]" mode="weaving" priority="0">
    
<xsl:message terminate="yes">[XWeaver] ERROR: Advices of type '<xsl:value-of select="ax:advice/@type" />' with codeModifiers of type '<xsl:value-of select="ax:advice/ax:codeModifier/@type" />' are not defined for '<xsl:value-of select="name()" />' srcML elements! </xsl:message>
  
</xsl:template>
  
  
  <xd:doc>
    
<xd:short>Default template for <b>not</b> annotated code. </xd:short>
    
<xd:detail>This template is called for all srcML elements, which do not have an advice as
    a subelement. It just copies the element and applies templates for its subelements.
</xd:detail>
  
</xd:doc>

  
<xsl:template match="*" mode="weaving">
    
<xsl:copy>
      
<xsl:copy-of select="@*" />
      
<xsl:apply-templates mode="weaving" />
    
</xsl:copy>
  
</xsl:template>
  
  
  <xd:doc>
    
<xd:short>Default template for advices.</xd:short>
    
<xd:detail>Advices are copied manually by the weaving rules.
    Therefore they shoud not be copied auotmatically. This template ensures
    that advices are not copied. 
</xd:detail>
  
</xd:doc>

  
<xsl:template match="ax:advice" mode="weaving" />

  
<!-- 
    ********************************************************
    
      Functions and named templates                       
    
    ********************************************************
  
-->
  
  <xd:doc>
    This template takes a block and adds the text given in the beginning of this block. 
    
<xd:param name="block" type="node-set">The block to add the text to</xd:param>
    
<xd:param name="advice" type="node-set">The advice to be woven</xd:param>
  
</xd:doc>

  
<xsl:template name="addAtBeginOfBlock">
    
<xsl:param name="block" />
    
<xsl:param name="advice" />

      
<!-- Single line block? (Curly braces are on the same line) -->   
      
<xsl:variable name="isSingleLineBlock" select="not(contains(string-join($block/text(),''), ' '))" />
      
      
<!-- Empty block? -->
      
<xsl:variable name="isEmptyBlock" select="count($block/text()) = 1" />

       
<xsl:choose>
        
<xsl:when test="$isEmptyBlock">
          
<!-- Block indent -->
          
<xsl:variable name="blockIndent" select="util:repeatString($defaultIndentation, count(ancestor::src:block))" />
          
<xsl:value-of select="'{ '" />
          
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), concat( $blockIndent, $defaultIndentation))" /></ax:inserted>
          
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
        
</xsl:when>
        
<xsl:otherwise>
          
<xsl:choose>
            
<xsl:when test="$isSingleLineBlock">
              
<!-- Block indent -->
              
<xsl:variable name="blockIndent" select="util:repeatString($defaultIndentation, count(ancestor::src:block))" />
              
<xsl:value-of select="'{ '" />
              
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), concat( $blockIndent, $defaultIndentation ))" /></ax:inserted>
              
<xsl:value-of select="concat(' ', $blockIndent, $defaultIndentation)" />
              
<xsl:copy-of select="$block/text()[1]/following-sibling::node()[not(self::ax:advice) and position() != last() ]" />
              
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
            
</xsl:when>
            
<xsl:when test="not($isSingleLineBlock)">
              
<!-- Block indent -->
              
<xsl:variable name="blockIndent">
                
<xsl:choose>
                  
<xsl:when test="contains($block/text()[1], ' ')">
                    
<xsl:value-of select="concat(util:repeatString($defaultIndentation, count(ancestor::src:block)), $defaultIndentation)" />
                  
</xsl:when>
                  
<xsl:otherwise>
                    
<xsl:value-of select="util:substringAfterLast($block/text()[1], ' ')" />
                  
</xsl:otherwise>
                
</xsl:choose>
              
</xsl:variable>
              
<xsl:value-of select="'{ '" />
              
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), $blockIndent )" /></ax:inserted>
              
<xsl:value-of select="concat(' ', $blockIndent)" />
              
<xsl:copy-of select="$block/text()[1]/following-sibling::node()[not(self::ax:advice)]" />
            
</xsl:when>
          
</xsl:choose>
        
</xsl:otherwise>
      
</xsl:choose>
  
</xsl:template>
 
 
 
  <xd:doc>
    This template takes a block and adds the text given at the end of this block.
    
<xd:param name="block" type="node-set">The block to add the text to</xd:param>
    
<xd:param name="text" type="string">The text to add at the end of the block</xd:param>
  
</xd:doc>

  
<xsl:template name="addElementsAtEndOfBlock">
    
<xsl:param name="block" />
    
<xsl:param name="elements" />
    
<xsl:param name="indent" select="'compute'" />
    
    
<xsl:variable name="element">
      
<xsl:for-each select="$elements">
        
<xsl:copy-of select="." />
        
<xsl:if test="position() != last()">
          
<xsl:text>
</xsl:text>
        
</xsl:if>
      
</xsl:for-each>
    
</xsl:variable>
    
    
    
      
<!-- Single line block? (Curly braces are on the same line) -->   
      
<xsl:variable name="isSingleLineBlock" select="not(contains(string-join($block//text(),''), ' '))" />
      
      
<!-- Empty block? -->
      
<xsl:variable name="isEmptyBlock" select="count($block/text()) = 1" />
      
      
<!-- Block indent -->
      
<xsl:variable name="blockIndent">
        
<xsl:choose>
          
<xsl:when test="$indent = 'compute'">
            
<xsl:value-of select="util:repeatString($defaultIndentation, count(ancestor::src:block))" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$indent" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>
      
      
<!-- Default indentation -->
      
<xsl:variable name="defaultIndentation">
        
<xsl:choose>
          
<xsl:when test="$indent = 'compute'">
            
<xsl:value-of select="$defaultIndentation" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$indent" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>
      
      
<xsl:choose>
        
<xsl:when test="$isEmptyBlock">
          
<xsl:value-of select="'{ '" />
          
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
          
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
        
</xsl:when>
        
<xsl:otherwise>
          
<xsl:choose>
            
<xsl:when test="$isSingleLineBlock">
              
<xsl:value-of select="concat('{ ', $blockIndent, $defaultIndentation)" />
              
<xsl:copy-of select="$block/node()[not(self::ax:advice)][position() != 1 and position() != last() ]" />
              
<xsl:text>
</xsl:text>
              
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
              
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
            
</xsl:when>
            
<xsl:when test="not($isSingleLineBlock)">
              
<xsl:copy-of select="$block/node()[not(self::ax:advice)][position() != last()]" />
              
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
              
<xsl:text>
</xsl:text>
              
<xsl:value-of select="$block/text()[position() = last()]" />
            
</xsl:when>
          
</xsl:choose>
        
</xsl:otherwise>
      
</xsl:choose>
  
</xsl:template>
 
  
  
  <xd:doc>
    This template takes a block and adds the text given in the beginning of this block. 
    
<xd:param name="block" type="node-set">The block to add the text to</xd:param>
    
<xd:param name="advice" type="node-set">The advice to be woven</xd:param>
  
</xd:doc>

  
<xsl:template name="addElementsAtBeginOfBlock">
    
<xsl:param name="block" />
    
<xsl:param name="elements" />
    
<xsl:param name="indent" select="'compute'" />
    
    
<xsl:variable name="element">
      
<xsl:for-each select="$elements">
        
<xsl:copy-of select="." />
        
<xsl:if test="position() != last()">
          
<xsl:text>
</xsl:text>
        
</xsl:if>
      
</xsl:for-each>
    
</xsl:variable>

      
<!-- Single line block? (Curly braces are on the same line) -->   
      
<xsl:variable name="isSingleLineBlock" select="not(contains(string-join($block//text(),''), ' '))" />
      
      
<!-- Empty block? -->
      
<xsl:variable name="isEmptyBlock" select="count($block/text()) = 1" />
      
      
<!-- Block indent -->
      
<xsl:variable name="blockIndent">
        
<xsl:choose>
          
<xsl:when test="$indent = 'compute'">
            
<xsl:value-of select="util:repeatString($defaultIndentation, count(ancestor::src:block))" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$indent" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>
      
      
<!-- Default indentation -->
      
<xsl:variable name="defaultIndentation">
        
<xsl:choose>
          
<xsl:when test="$indent = 'compute'">
            
<xsl:value-of select="$defaultIndentation" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="$indent" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:variable>
      
       
<xsl:choose>
        
<xsl:when test="$isEmptyBlock">
          
<xsl:value-of select="'{ '" />
          
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
          
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
        
</xsl:when>
        
<xsl:otherwise>
          
<xsl:choose>
            
<xsl:when test="$isSingleLineBlock">
              
<xsl:value-of select="'{ '" />
              
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
              
<xsl:value-of select="concat(' ', $blockIndent, $defaultIndentation)" />
              
<xsl:copy-of select="$block/text()[1]/following-sibling::node()[not(self::ax:advice) and position() != last() ]" />
              
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
            
</xsl:when>
            
<xsl:when test="not($isSingleLineBlock)">
              
<xsl:value-of select="'{ '" />
              
<xsl:copy-of select="xw:indentElement($element, concat( $blockIndent, $defaultIndentation))" />
              
<xsl:value-of select="concat(' ', $blockIndent, $defaultIndentation)" />
              
<xsl:copy-of select="$block/text()[1]/following-sibling::node()[not(self::ax:advice)]" />
            
</xsl:when>
          
</xsl:choose>
        
</xsl:otherwise>
      
</xsl:choose>
  
</xsl:template>
  
  
  <xd:doc>
    This template takes a block and adds the text given at the end of this block.
    
<xd:param name="block" type="node-set">The block to add the text to</xd:param>
    
<xd:param name="text" type="string">The text to add at the end of the block</xd:param>
  
</xd:doc>

  
<xsl:template name="addAtEndOfBlock">
    
<xsl:param name="block" />
    
<xsl:param name="advice" />

      
<!-- Single line block? (Curly braces are on the same line) -->   
      
<xsl:variable name="isSingleLineBlock" select="not(contains(string-join($block/text(),''), ' '))" />
      
      
<!-- Empty block? -->
      
<xsl:variable name="isEmptyBlock" select="count($block/text()) = 1" />
      
      
<!-- Block indent -->
      
<xsl:variable name="blockIndent" select="util:repeatString($defaultIndentation, count(ancestor::src:block))" />
     
      
<xsl:choose>
        
<xsl:when test="$isEmptyBlock">
          
<xsl:value-of select="'{ '" />
          
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), concat( $blockIndent, $defaultIndentation))" /></ax:inserted>
          
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
        
</xsl:when>
        
<xsl:otherwise>
          
<xsl:choose>
            
<xsl:when test="$isSingleLineBlock">
              
<xsl:value-of select="concat('{ ', $blockIndent, $defaultIndentation)" />
              
<xsl:copy-of select="$block/node()[not(self::ax:advice)][position() != 1 and position() != last() ]" />
              
<xsl:text>
</xsl:text>
              
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), concat( $blockIndent, $defaultIndentation))" /></ax:inserted>
              
<xsl:value-of select="concat( ' ', $blockIndent, '}')" />
            
</xsl:when>
            
<xsl:when test="not($isSingleLineBlock)">
              
<xsl:copy-of select="$block/node()[not(self::ax:advice)][position() != last()]" />
              
<xsl:text>
</xsl:text>
              
<ax:inserted><xsl:value-of select="util:indentText(xw:getCodeModifierContent($advice/ax:codeModifier), concat( $blockIndent, $defaultIndentation))" /></ax:inserted>
              
<xsl:value-of select="$block/text()[position() = last()]" />
            
</xsl:when>
          
</xsl:choose>
        
</xsl:otherwise>
      
</xsl:choose>
  
</xsl:template>

  
  <xd:doc>
    Returns the string containing all text() nodes from the given sequence of codeModifiers.
    The markup with codeModifier and text elements is transformed to newlines.
    
<xd:param name="codeModifiers" type="node-set">Sequence of codeModifier elements</xd:param>
  
</xd:doc>

  
<xsl:function name="xw:getCodeModifierContent">
    
<xsl:param name="codeModifiers" />
    
<xsl:variable name="return">
      
<xsl:for-each select="$codeModifiers">
        
<xsl:for-each select="ax:text">
          
<xsl:value-of select="." />
          
<xsl:if test="position() != last()">
            
<xsl:text>
</xsl:text>
          
</xsl:if>
        
</xsl:for-each>
        
<xsl:if test="position() != last()">
          
<xsl:text>
</xsl:text>
        
</xsl:if>
      
</xsl:for-each>
    
</xsl:variable>
    
<xsl:value-of select="string-join($return,'')" />
  
</xsl:function>
  
  
  <xd:doc>
    Adds indentation to an element.
    
<xd:param name="element" type="string">The text the indentation should be added to.</xd:param>
    
<xd:param name="indent" type="string">String that is used for indentation. </xd:param>
    
<xd:param name="indentFirstLine" type="boolean">If true the first line is not indented </xd:param>
  
</xd:doc>

  
<xsl:function name="xw:indentElement">
    
<xsl:param name="element" />
    
<xsl:param name="indent" />
    
<xsl:value-of select="$indent" />
    
<xsl:apply-templates select="$element" mode="indentElement">
      
<xsl:with-param name="indent" select="$indent" />
    
</xsl:apply-templates>
  
</xsl:function>
  
  
<xsl:template match="*" mode="indentElement">
    
<xsl:param name="indent" />
    
<xsl:copy>
      
<xsl:copy-of select="@*" />
      
<xsl:apply-templates mode="indentElement">
        
<xsl:with-param name="indent" select="$indent" />
      
</xsl:apply-templates>
    
</xsl:copy>
  
</xsl:template>
  
  
<xsl:template match="text()[contains(.,' ')]" mode="indentElement">
    
<xsl:param name="indent" />
    
<xsl:value-of select="replace( ., ' ', concat(' ', $indent) )" />
  
</xsl:template>
</xsl:stylesheet>






































v