<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">
  
  
     <xd:doc type="stylesheet">
    
<xd:short>Weaving Rule that adds a declaration to a class</xd:short>
    
<xd:detail>
      
<ul> 
        
<li>srcML element:     <code>src:class</code></li>
        
<li>advice type:       <code>add</code></li>
        
<li>codeModifier type: <code>declaration</code></li>
      
</ul>
      Adds a declaration to the first possible location of the following choices:
      
<ul>
        
<li>Check if appropriate access modifiers exist, if not add an advice to the class so they are added the next time.</li>
        
<li>If all access modifiers have been added, the add advices of the class are moved to the access modifier elements.</li>
      
</ul>
      
<h2>Example 1</h2>
      
<h3>Base Code</h3>
      
<div class="source">
<pre>class Foo {
  public:
}
</pre>
      
</div>
      
<h3>Code Modifier</h3>
      
<xd:xml>
<codeModifier type="declaration">
    
<accessModifier type="public" />
    
<text>int foo();</text>
</codeModifier>
      
</xd:xml>
      
<h3>Modified Code</h3>
      
<div class="source">
      
<pre>class Foo {
  public:
    
<span class="highlightedCode">int foo();</span>
}
</pre>
      
</div>
      
<h2>Example 2</h2>
      
<p>Access modifier blocks are added by the weaver if needed.</p>
      
<h3>Base Code</h3>
      
<div class="source">
<pre>class Foo {
  public:
    int foo1();
}
</pre>
      
</div>
      
<h3>Code Modifier</h3>
      
<xd:xml>
<codeModifier type="declaration">
    
<accessModifier type="private" />
    
<text>int foo2();</text>
</codeModifier>
      
</xd:xml>
      
<h3>Modified Code</h3>
      
<div class="source">
      
<pre>class Foo {
  public:
    int foo1();
  private:
    
<span class="highlightedCode">int foo2();</span>
}
</pre>
      
</div>
      
<xd:weaverRuleLinks pointcutType="src:class" adviceType="add" codeModifierType="declaration" />
    
</xd:detail>
    
<xd:cvsId>$Id$</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="*" />
  
  
     <xd:doc>
    
<xd:detail>
      This template does the following:
      
<ul>
        
<li>Check if appropriate access modifiers exist, if not add an advice to the class so they are added the next time.</li>
        
<li>If all access modifiers have been added, the add advices of the class are moved to the access modifier elements.</li>
      
</ul>
    
</xd:detail>
  
</xd:doc>

  
<xsl:template match="src:class[ax:advice[@type='add' and position() = 1]/ax:codeModifier[@type='declaration']]" mode="weaving">
    
<xsl:variable name="advice" select="ax:advice[1]" />
    
<xsl:variable name="class" select="." />
    
<!-- Asserts -->
    
<xsl:choose>
      
<xsl:when test="not(.//src:block)">
        
<!-- This should not happen anymore, as srcML now has an element class_decl for class decalarations -->
        
<xsl:message terminate="yes">ERROR: Cannot weave classes, which do not have a body (block element). Use .//block in the constraint of a 
        class join point to exclude forward declarations from being annotated.
</xsl:message>
      
</xsl:when>
      
<xsl:when test="exists(ax:advice/ax:codeModifier[not(ax:accessModifier)])">
        
<xsl:message terminate="yes">ERROR: A declaration codeModifier must contain an accessModifier child elmement of type 'public', 'private', 'protected' or 'default'.</xsl:message>
      
</xsl:when>
    
</xsl:choose>    
    
<!-- Go through all code modifiers of all advices and test if access modifiers exist in the base code, if not, add the appropriate -->
    
<xsl:variable name="additionalAccessModifiersAdvice">
      
<ax:advice type="add">
        
<ax:codeModifier type="accessModifierBlock">
        
<xsl:for-each-group select="ax:advice/ax:codeModifier/ax:accessModifier" group-by="@type">
          
<xsl:choose>
            
<xsl:when test="current()/@type = 'public' and count($class//src:public) = 0">
              
<ax:accessModifierBlock type="public" />
            
</xsl:when>
            
<xsl:when test="current()/@type = 'protected' and count($class//src:protected) = 0">
              
<ax:accessModifierBlock type="protected" />
            
</xsl:when>
            
<xsl:when test="current()/@type = 'private' and count($class//src:private[not(@type) or @type != 'default']) = 0">
              
<ax:accessModifierBlock type="private" />
            
</xsl:when>
          
</xsl:choose>
        
</xsl:for-each-group>
        
</ax:codeModifier>
      
</ax:advice>
    
</xsl:variable>
    
    
<xsl:variable name="modifiedClass">
      
<xsl:choose>
        
<!-- Add access modifier block to class -->
        
<xsl:when test="count($additionalAccessModifiersAdvice/ax:advice/ax:codeModifier/ax:accessModifierBlock) &gt; 0">
          
<xsl:copy>
            
<xsl:copy-of select="@*" />
            
<!-- copy new advices for this class -->
            
<xsl:copy-of select="$additionalAccessModifiersAdvice" />
            
<!-- copy everything else -->
            
<xsl:copy-of select="child::node()" />
          
</xsl:copy>
        
</xsl:when>
        
<xsl:otherwise>
          
<!-- Move the declaration advices defined for the class to the appropriate accessModifier blocks -->
          
<xsl:copy>
            
<xsl:copy-of select="@*" />
            
<!-- copy all advices except the ones to be moved -->
            
<xsl:copy-of select="ax:advice[not(@type='add' and ax:codeModifier/@type='declaration')]" />
            
<!-- Copy everything else and add advices to be moves at the rigth location -->
            
<xsl:apply-templates select="child::node()[not(self::ax:advice)]" mode="class_add_declaration_move_declarations">
              
<xsl:with-param name="advices" select="ax:advice[@type='add' and ax:codeModifier/@type='declaration']" />
            
</xsl:apply-templates>
          
</xsl:copy>
        
</xsl:otherwise>
      
</xsl:choose>
    
</xsl:variable>
    
<xsl:apply-templates select="$modifiedClass" mode="weaving" />
  
</xsl:template>
  
  
     <xd:doc>
    Move advices to the appropriate access modifier element.
  
</xd:doc>

  
<xsl:template match="src:public | src:private | src:protected" mode="class_add_declaration_move_declarations">
    
<xsl:param name="advices" />
    
<xsl:variable name="accessModifierString">
      
<xsl:choose>
        
<xsl:when test="@type='default'">
          
<xsl:text>default</xsl:text>
        
</xsl:when>
        
<xsl:otherwise>
          
<xsl:value-of select="local-name()" />
        
</xsl:otherwise>
      
</xsl:choose>    
    
</xsl:variable>
    
<xsl:copy>
      
<xsl:copy-of select="@*" />
      
<xsl:for-each select="$advices[ax:codeModifier/ax:accessModifier/@type = $accessModifierString]">
        
<xsl:copy>
          
<xsl:copy-of select="@*" />
          
<xsl:for-each select="ax:codeModifier">
            
<xsl:if test="ax:accessModifier/@type = $accessModifierString">
              
<xsl:copy-of select="." />
            
</xsl:if>
          
</xsl:for-each>
        
</xsl:copy>
      
</xsl:for-each>
      
<xsl:copy-of select="child::node()" />
    
</xsl:copy>
  
</xsl:template>
  
  
  
     <xd:doc>
    Default copy template for class_add_declaration_move_declarations.
  
</xd:doc>

  
<xsl:template match="*" mode="class_add_declaration_move_declarations">
    
<xsl:param name="advices" />
    
<xsl:copy>
      
<xsl:copy-of select="@*" />
      
<xsl:apply-templates mode="class_add_declaration_move_declarations">
        
<xsl:with-param name="advices" select="$advices" />
      
</xsl:apply-templates>
    
</xsl:copy>
  
</xsl:template>
</xsl:stylesheet>






































v