<?xml version="1.0"?>

<!--
A stylesheet to transform CellML into a Virtual Cell BioModel.
-->

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:cellml="http://www.cellml.org/cellml/1.0#" 
  xmlns:mathml="http://www.w3.org/1998/Math/MathML" 
  xmlns:nameList="cbit.vcell.xml.NameList" 
  xmlns:nameManager="cbit.vcell.xml.NameManager" 
  xmlns:expression="cbit.vcell.parser.Expression" 
  exclude-result-prefixes="cellml mathml expression nameManager nameList" 
  extension-element-prefixes="nameManager expression nameList">
  
  
	<!-- default parameters -->
	<xsl:output method="xml" indent="yes"/>
	
	<!-- Create a name manager to handle variable mappings and
    name mangling -->
	<xsl:variable name="nameManager" select="nameManager:new()"/>
  
	<!-- and a hash table to keep track of the compounds as they are declared -->
	<xsl:variable name="compoundList" select="nameList:new()"/>
	<!-- and another one to keep a global list of parameters to ensure that 
    parameters get a unique name when they are used in more than one reaction -->
	<xsl:variable name="gParamList" select="nameList:new()"/>
  
 	<!-- Beginning of styleshet-->
	<xsl:template match="/">
		<xsl:message>Transforming CELLML into a VCML BioModel</xsl:message>
		<xsl:message>Assuming the bound variable is always time</xsl:message>
		<xsl:comment>VCML created from a CELLML document</xsl:comment>
		<xsl:apply-templates select="cellml:model"/>
	</xsl:template>
  
	<!-- cellml:model -->
	<xsl:template match="cellml:model">
    <!-- Create the BioModel -->
		<xsl:element name="BioModel">
			<xsl:attribute name="Name">
        <xsl:value-of select="@name"/>
      </xsl:attribute>
      <!-- create the Model -->
      <xsl:element name="Model">
        <xsl:attribute name="Name">
          <xsl:value-of select="@name"/>
        </xsl:attribute>
        <!-- Define a single compartment -->
        <xsl:element name="Feature">
          <xsl:attribute name="Name">
            <xsl:value-of select="@name"/>
          </xsl:attribute>
        </xsl:element>
        
        <!-- add all the components and variables to the name manager -->
        <xsl:for-each select="cellml:component/cellml:variable">
          <xsl:variable name="addingDummy" select="nameManager:add($nameManager,../@name,@name)"/>
        </xsl:for-each>
        <!-- and resolve all connections -->
        <xsl:for-each select="cellml:connection">
          <xsl:variable name="component1" select="cellml:map_components/@component_1"/>
          <xsl:variable name="component2" select="cellml:map_components/@component_2"/>
          <xsl:for-each select="cellml:map_variables">
            <xsl:variable name="variable1" select="@variable_1"/>
            <xsl:variable name="variable2" select="@variable_2"/>
            <xsl:choose>
              <xsl:when test="../../cellml:component[@name=$component1]/cellml:variable[(@name=$variable1) and
                  not((@public_interface = 'in') or (@private_interface = 'in'))]">
                <!-- component1/variable1 is the "output" variable so connect component2/variable2 to it -->
                <xsl:variable name="resolveDummy" 
                    select="nameManager:connect($nameManager,$component2,$variable2,$component1,$variable1)"/>
              </xsl:when>
              <xsl:otherwise>
                <!-- component2/variable2 is the "output" variable so connect component1/variable1 to it -->
                <xsl:variable name="resolveDummy" 
                    select="nameManager:connect($nameManager,$component1,$variable1,$component2,$variable2)"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:for-each>
				<!-- create all the resolved mangled names -->
				<xsl:variable name="mangling-tmp" select="nameManager:generateMangledNames($nameManager)"/>


        <!-- Declare the Compounds -->
        <xsl:for-each select="cellml:component/cellml:reaction">
          <xsl:call-template name="declare-compounds"/>
        </xsl:for-each>
        <!-- now add all the reactions -->
        <xsl:for-each select="cellml:component/cellml:reaction">
          <xsl:variable name="counter" select="position()"/>
          <xsl:call-template name="define-reactions">
            <xsl:with-param name="counter" select="$counter"/>
          </xsl:call-template>
        </xsl:for-each>
      </xsl:element> <!-- Model -->
		</xsl:element> <!-- BioModel -->
	</xsl:template>	<!-- cellml:model -->
  
  <!-- 
  Named Template: declare-compounds
  Context node: cellml:reaction
  Declares all the compounds defined in the context reaction
  -->
  <xsl:template name="declare-compounds">
    <!--xsl:message>
      <xsl:value-of 
        select="concat('Declaring compounds for component: ',@name)"/>
    </xsl:message-->
    <!-- Loop through all the variables which might be compounds -->
    <xsl:for-each select="cellml:variable_ref[cellml:role/@role != 'rate']">
      <!-- we have a compound - declare it if it is not already defined -->
      <xsl:variable name="compound-name" 
          select="nameManager:getMangledName($nameManager,../../@name,@variable)"/>
      <xsl:if test="string-length($compound-name) = 0">
        <xsl:message terminate="no">
          <xsl:text>declare-compounds: Unable to resolve the variable &quot;</xsl:text>
          <xsl:value-of select="@variable"/>
          <xsl:text>&quot; in the component &quot;</xsl:text>
          <xsl:value-of select="../../@name"/><xsl:text>&quot;</xsl:text>
        </xsl:message>
      </xsl:if>
      <!-- we need the resolved component and variable name -->
      <xsl:variable name="Component" select="nameManager:getFirstSecondKey($nameManager,$compound-name)"/>
      <xsl:variable name="Variable" select="nameManager:getMangledName($nameManager,$compound-name,$Component)"/>
      <xsl:variable name="declared-compound" 
        select="nameList:getMangledName($compoundList,$Variable,$Component)"/>
      <xsl:if test="string-length($declared-compound) = 0">
        <!-- The coumpound has not been declared, so declare it and add
             it to the list of declared compounds -->
        <xsl:element name="Compound">
          <xsl:attribute name="Name">
            <xsl:value-of select="$compound-name"/>
          </xsl:attribute>
          <xsl:attribute name="CommonName">
            <xsl:value-of select="$compound-name"/>
          </xsl:attribute>
        </xsl:element> <!-- Compound -->
        <!-- and a localised compound -->
        <xsl:element name="LocalizedCompound">
          <xsl:attribute name="Name">
            <xsl:value-of select="$compound-name"/>
          </xsl:attribute>
          <xsl:attribute name="CompoundRef">
            <xsl:value-of select="$compound-name"/>
          </xsl:attribute>
          <xsl:attribute name="Structure">
            <!-- the single compartment is named with the model identifier -->
            <xsl:value-of select="/cellml:model/@name"/>
          </xsl:attribute>
          <xsl:element name="Initial">
            <xsl:variable name="initial-value" 
              select="/cellml:model/cellml:component[@name=$Component]/cellml:variable[@name=$Variable]/@initial_value"/>
            <xsl:choose>
              <xsl:when test="string-length($initial-value) > 0">
                <xsl:value-of select="$initial-value"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:text>0.0</xsl:text>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:element>
          <xsl:element name="Diffusion">
            <xsl:text>0.0</xsl:text>
          </xsl:element>
        </xsl:element> <!-- LocalizedCompound -->
        <!-- Add the compound to the list -->
        <xsl:variable name="tmp" select="nameList:setMangledName(
          $compoundList,$Variable,$Component,$compound-name)"/>
      </xsl:if> <!-- string-length($declared-compound) = 0 -->
    </xsl:for-each> <!-- variable_ref -->
    <!-- we also need to add the rate variables to the component list to stop 
      them being declared as parameters -->
    <xsl:for-each select="cellml:variable_ref[cellml:role/@role = 'rate']">
      <xsl:variable name="rate-name" 
          select="nameManager:getMangledName($nameManager,../../@name,@variable)"/>
      <xsl:if test="string-length($rate-name) = 0">
        <xsl:message terminate="no">
          <xsl:text>declare-compounds: Unable to resolve the variable &quot;</xsl:text>
          <xsl:value-of select="@variable"/>
          <xsl:text>&quot; in the component &quot;</xsl:text>
          <xsl:value-of select="../../@name"/><xsl:text>&quot;</xsl:text>
        </xsl:message>
      </xsl:if>
      <!-- we need the resolved component and variable name -->
      <xsl:variable name="Component" select="nameManager:getFirstSecondKey($nameManager,$rate-name)"/>
      <xsl:variable name="Variable" select="nameManager:getMangledName($nameManager,$rate-name,$Component)"/>
      <xsl:variable name="dummy" 
        select="nameList:setMangledName($compoundList,$Variable,$Component,'dummy-for-a-rate')"/>
    </xsl:for-each>
  </xsl:template> <!-- declare-compounds -->

  <!--
  Named Template: define-reactions
  Context Node: cellml:reaction
  Converts CellML reaction elements into VCML SimpleReaction's
  -->
  <xsl:template name="define-reactions">
    <xsl:param name="counter"/>
    <xsl:element name="SimpleReaction">
      <xsl:attribute name="Name">
        <xsl:value-of select="../@name"/><!-- concat('cellml-reaction-',$counter)-->
      </xsl:attribute>
      <xsl:attribute name="Structure">
        <!-- the single compartment is named with the model name identifier -->
        <xsl:value-of select="../../@name"/>
      </xsl:attribute>
      <!-- Now set the participating species -->
      <xsl:for-each select="cellml:variable_ref">
        <xsl:choose>
          <xsl:when test="cellml:role/@role = 'reactant'">
            <xsl:element name="Reactant">
              <xsl:attribute name="LocalizedCompoundRef">
                <xsl:variable name="var" select="nameManager:getMangledName($nameManager,../../@name,@variable)"/>
                <xsl:if test="string-length($var) = 0">
                  <xsl:message terminate="no">
                    <xsl:text>define-reactions: Unable to resolve the variable &quot;</xsl:text>
                    <xsl:value-of select="@variable"/>
                    <xsl:text>&quot; in the component &quot;</xsl:text>
                    <xsl:value-of select="../../@name"/><xsl:text>&quot;</xsl:text>
                  </xsl:message>
                </xsl:if>
                <xsl:value-of select="$var"/>
              </xsl:attribute>
              <!-- For now, assume a stoichiometry of 1 if it is not 
                specified in the CellML - if its not specified, then there
                should be some maths which will override this anyway ?? -->
              <xsl:attribute name="Stoichiometry">
                <xsl:choose>
                  <xsl:when test="cellml:role/@stoichiometry">
                    <xsl:value-of select="cellml:role/@stoichiometry"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:text>1</xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:attribute>
            </xsl:element>
          </xsl:when>
          <xsl:when test="cellml:role/@role = 'product'">
            <xsl:element name="Product">
              <xsl:attribute name="LocalizedCompoundRef">
                <xsl:variable name="var2" select="nameManager:getMangledName($nameManager,../../@name,@variable)"/>
                <xsl:if test="string-length($var2) = 0">
                  <xsl:message terminate="no">
                    <xsl:text>define-reactions: Unable to resolve the variable &quot;</xsl:text>
                    <xsl:value-of select="@variable"/>
                    <xsl:text>&quot; in the component &quot;</xsl:text>
                    <xsl:value-of select="../../@name"/><xsl:text>&quot;</xsl:text>
                  </xsl:message>
                </xsl:if>
                <xsl:value-of select="$var2"/>
              </xsl:attribute>
              <!-- For now, assume a stoichiometry of 1 if it is not 
                specified in the CellML - if its not specified, then there
                should be some maths which will override this anyway ?? -->
              <xsl:attribute name="Stoichiometry">
                <xsl:choose>
                  <xsl:when test="cellml:role/@stoichiometry">
                    <xsl:value-of select="cellml:role/@stoichiometry"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:text>1</xsl:text>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:attribute>
            </xsl:element>
          </xsl:when>
          <xsl:when test="cellml:role/@role = 'rate'">
            <!-- write out the kinetics ?? -->
            <xsl:element name="Kinetics">
              <!-- ???
                For now, assume that there is only going to be one math element
                and that it contains the reaction kinetics
              ??? -->
              <xsl:attribute name="KineticsType">
                <xsl:text>GeneralKinetics</xsl:text>
              </xsl:attribute>
              <xsl:call-template name="define-reaction-kinetics">
                <xsl:with-param name="math" 
                  select="cellml:role/mathml:math"/>
                <xsl:with-param name="component" select="../.."/>
                <xsl:with-param name="rate-variable" select="@variable"/>
              </xsl:call-template>
            </xsl:element>
          </xsl:when>
          <xsl:otherwise>
            <!-- assume variable represents a modifier -->
            <xsl:element name="Modifier">
              <xsl:attribute name="LocalizedCompoundRef">
                <xsl:variable name="var3" select="nameManager:getMangledName($nameManager,../../@name,@variable)"/>
                <xsl:if test="string-length($var3) = 0">
                  <xsl:message terminate="no">
                    <xsl:text>define-reactions: Unable to resolve the variable &quot;</xsl:text>
                    <xsl:value-of select="@variable"/>
                    <xsl:text>&quot; in the component &quot;</xsl:text>
                    <xsl:value-of select="../../@name"/><xsl:text>&quot;</xsl:text>
                  </xsl:message>
                </xsl:if>
                <xsl:value-of select="$var3"/>
              </xsl:attribute>
            </xsl:element>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
    </xsl:element>
  </xsl:template> <!-- define-reactions -->
  
  <!--
  Named Template: define-reaction-kinetics
  Takes a pointer to a <math> element and to its parent <component> element
  and processes the maths to define the kinetics for the reaction.
  -->
  <xsl:template name="define-reaction-kinetics">
    <!-- the MathML math node -->
    <xsl:param name="math"/>
    <!-- the parent component node -->
    <xsl:param name="component"/>
    <!-- the rate variable name -->
    <xsl:param name="rate-variable"/>
    
   	<!-- we need to keep track of the parameters as 
      they are declared -->
   	<xsl:variable name="paramList" select="nameList:new()"/>
    <!-- and their unique identifiers -->
   	<xsl:variable name="mangledParamList" select="nameList:new()"/>
    
    <!-- add all the variables declared in the component but not already
      defined as compounds as parameters in the kinetics -->
    <xsl:for-each select="$component/cellml:variable">
      <xsl:variable name="parameter-name" select="nameManager:getMangledName($nameManager,../@name,@name)"/>
      <xsl:if test="string-length($parameter-name) = 0">
        <xsl:message terminate="no">
          <xsl:text>define-reaction-kinetics: Unable to resolve the variable &quot;</xsl:text>
          <xsl:value-of select="@name"/>
          <xsl:text>&quot; in the component &quot;</xsl:text>
          <xsl:value-of select="../@name"/><xsl:text>&quot;</xsl:text>
        </xsl:message>
      </xsl:if>
      <!-- need to get the resolved component and variable names -->
      <xsl:variable name="Component" select="nameManager:getFirstSecondKey($nameManager,$parameter-name)"/>
      <xsl:variable name="Variable" select="nameManager:getMangledName($nameManager,$parameter-name,$Component)"/>
      <xsl:variable name="declared-compound" 
        select="nameList:getMangledName($compoundList,$Variable,$Component)"/>
      <!--xsl:message>
        <xsl:text>
Component: </xsl:text><xsl:value-of select="$Component"/><xsl:text>
Variable: </xsl:text><xsl:value-of select="$Variable"/><xsl:text>
Name: </xsl:text><xsl:value-of select="$declared-compound"/>
      </xsl:message-->
      <xsl:if test="string-length($declared-compound) = 0">
        <!-- the variable is not a compound, so make it a parameter -->
        <xsl:call-template name="define-reaction-parameter">
          <xsl:with-param name="parameter-name" select="$parameter-name"/>
          <xsl:with-param name="paramList" select="$paramList"/>
          <xsl:with-param name="mangledParamList" select="$mangledParamList"/>
          <xsl:with-param name="Variable" select="$Variable"/>
          <xsl:with-param name="Component" select="$Component"/>
          <xsl:with-param name="component" select="/cellml:model/cellml:component[@name=$Component]"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:for-each> <!-- declaring parameters -->
    <!-- Convert the rate equation in the math element into a VCell
      infix expression -->
    <!--xsl:message>
      <xsl:text>rate-variable = &quot;</xsl:text>
      <xsl:value-of select="$rate-variable"/>
      <xsl:text>&quot;</xsl:text>
    </xsl:message-->
    <xsl:variable name="rhs-node" 
      select="$math/mathml:apply/mathml:eq/following-sibling::mathml:ci[normalize-space(.) = $rate-variable]/following-sibling::node()"/>
    <!--xsl:message>
      <xsl:text>RHS node = &quot;</xsl:text>
      <xsl:value-of select="string($rhs-node)"/>
      <xsl:text>&quot;</xsl:text>
    </xsl:message-->
    <xsl:if test="not($rhs-node)">
      <xsl:message terminate="yes">
        <xsl:text>Unable to find the rate equation for rate variable </xsl:text>
        <xsl:value-of select="$rate-variable"/>
        <xsl:text> in component </xsl:text>
        <xsl:value-of select="ancestor::cellml:component/@name"/>
      </xsl:message>
    </xsl:if>
    <xsl:variable name="vcell-expression" 
      select="expression:getInfixStringFromMathML($rhs-node)"/>
    <xsl:element name="Rate">
      <!-- post-process the equation -->
      <xsl:variable name="equation">
        <xsl:call-template name="post-process-math-expression">
          <xsl:with-param name="expression" select="$vcell-expression"/>
          <xsl:with-param name="component" select="$component"/>
        </xsl:call-template>
      </xsl:variable>
      <!-- Now we need to check for any parameters in the equation
        who need to have their name changed -->
      <xsl:variable name="tmp">
        <xsl:call-template name="mangle-parameter-names">
          <xsl:with-param name="expression" select="$equation"/>
          <xsl:with-param name="paramList" select="$mangledParamList"/>
        </xsl:call-template>
      </xsl:variable>
      <!-- and add a minus sign to the equation -->
      <xsl:variable name="tmp2" select="concat('(-(',$tmp,'))')"/>
      <!-- and write it out -->
      <xsl:value-of select="$tmp2"/>
    </xsl:element> <!-- Rate -->
  </xsl:template> <!-- define-reaction-kinetics -->

  <!--  
  Named template: define-reaction-parameter
  -->
  <xsl:template name="define-reaction-parameter">
    <!-- the mangled identifier -->
    <xsl:param name="parameter-name"/>
    <!-- the list of parameters for this reaction -->
    <xsl:param name="paramList"/>
    <!-- and their mapping to a unique parameter identifier -->
    <xsl:param name="mangledParamList"/>
    <!-- the actual variable name (resolved) -->
    <xsl:param name="Variable"/>
    <!-- the actual component name (resolved) -->
    <xsl:param name="Component"/>
    <!-- and the corresponding element pointer -->
    <xsl:param name="component"/>
    
    <!-- check if the parameter is already defined -->
    <xsl:variable name="declared-parameter" select="nameList:getMangledName(
      $paramList,$Variable,$Component)"/>
    <!--xsl:message>
      <xsl:text>Getting from the parameter list: </xsl:text>
      <xsl:value-of select="$Variable"/><xsl:text>,</xsl:text>
      <xsl:value-of select="$Component"/><xsl:text>,</xsl:text>
      <xsl:value-of select="$declared-parameter"/>
    </xsl:message-->
    <xsl:if test="string-length($declared-parameter) = 0">
      <!-- and add it to the list of parameters for this reaction -->
      <!--xsl:message>
        <xsl:text>Adding to the parameter list: </xsl:text>
        <xsl:value-of select="$Variable"/><xsl:text>,</xsl:text>
        <xsl:value-of select="$Component"/><xsl:text>,</xsl:text>
        <xsl:value-of select="$parameter-name"/>
      </xsl:message-->
      <xsl:variable name="dummy" select="nameList:setMangledName(
        $paramList,$Variable,$Component,$parameter-name)"/>
      <!-- need to check for a value/expression for the parameter -->
      <xsl:variable name="param-component" select="/cellml:model/cellml:component[@name=$Component]"/>
      <xsl:variable name="param-variable" select="$param-component/cellml:variable[@name=$Variable]"/>
      <xsl:variable name="param-rhs" 
        select="$param-component//mathml:math/mathml:apply/mathml:eq/following-sibling::mathml:ci[
          normalize-space(.) = $Variable]/following-sibling::node()"/>
      <xsl:choose>
        <xsl:when test="$param-rhs">
          <!-- we first need to declare any new parameters that may be 
            in this parameters equation -->
          <xsl:for-each select="$param-rhs//mathml:ci">
            <!-- check for already declared parameters and compounds -->
            <xsl:variable name="var-name" select="nameManager:getMangledName($nameManager,$Component,normalize-space(.))"/>
            <xsl:if test="string-length($var-name) = 0">
              <xsl:message terminate="no">
                <xsl:text>define-reaction-parameter: Unable to resolve the variable &quot;</xsl:text>
                <xsl:value-of select="normalize-space(.)"/>
                <xsl:text>&quot; in the component &quot;</xsl:text>
                <xsl:value-of select="$Component"/><xsl:text>&quot;</xsl:text>
              </xsl:message>
            </xsl:if>
            <xsl:variable name="var-component" select="nameManager:getFirstSecondKey($nameManager,$var-name)"/>
            <xsl:variable name="var-variable" select="nameManager:getMangledName($nameManager,$var-name,$var-component)"/>
            <xsl:variable name="var-declared-compound" 
              select="nameList:getMangledName($compoundList,$var-variable,$var-component)"/>
            <xsl:variable name="var-declared-param" 
              select="nameList:getMangledName($paramList,$var-variable,$var-component)"/>
            <xsl:if test="((string-length($var-declared-compound)=0) and 
              (string-length($var-declared-param)=0))">
              <!-- the variable is neither a compound or a declared 
                parameter, so we need to define it -->
              <xsl:call-template name="define-reaction-parameter">
                <xsl:with-param name="parameter-name" select="$var-name"/>
                <xsl:with-param name="paramList" select="$paramList"/>
                <xsl:with-param name="mangledParamList" select="$mangledParamList"/>
                <xsl:with-param name="Variable" select="$var-variable"/>
                <xsl:with-param name="Component" select="$var-component"/>
                <xsl:with-param name="component" select="/cellml:model/cellml:component[@name=$Component]"/>
              </xsl:call-template>
            </xsl:if>
          </xsl:for-each>
          <xsl:variable name="vcell-expression" 
            select="expression:getInfixStringFromMathML($param-rhs)"/> 
          <xsl:element name="Parameter">
            <xsl:attribute name="Name">
              <!-- get a unique parameter name for the parameter -->
              <xsl:variable name="unique-id">
                <xsl:call-template name="get-unique-parameter-name">
                  <xsl:with-param name="param-name" select="$parameter-name"/>
                </xsl:call-template>
              </xsl:variable>
              <!-- add it to the hashtable -->
              <xsl:variable name="dummy1" select="nameList:setMangledName(
                $mangledParamList,$parameter-name,'dummy',$unique-id)"/>
              <!-- and write it out -->
              <xsl:value-of select="$unique-id"/>
            </xsl:attribute>
            <!-- post-process the equation -->
            <xsl:variable name="equation">
              <xsl:call-template name="post-process-math-expression">
                <xsl:with-param name="expression" select="$vcell-expression"/>
                <xsl:with-param name="component" select="$component"/>
              </xsl:call-template>
            </xsl:variable>
            <!-- Now we need to check for any parameters in the equation
              who need to have their name changed -->
            <xsl:variable name="tmp">
              <xsl:call-template name="mangle-parameter-names">
                <xsl:with-param name="expression" select="$equation"/>
                <xsl:with-param name="paramList" select="$mangledParamList"/>
              </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select="$tmp"/>
          </xsl:element>
        </xsl:when>
        <xsl:when test="$param-variable/@initial_value">
          <xsl:element name="Parameter">
            <xsl:attribute name="Name">
              <!-- get a unique parameter name for the parameter -->
              <xsl:variable name="unique-id">
                <xsl:call-template name="get-unique-parameter-name">
                  <xsl:with-param name="param-name" select="$parameter-name"/>
                </xsl:call-template>
              </xsl:variable>
              <!-- add it to the hashtable -->
              <xsl:variable name="dummy2" select="nameList:setMangledName(
                $mangledParamList,$parameter-name,'dummy',$unique-id)"/>
              <!-- and write it out -->
              <xsl:value-of select="$unique-id"/>
            </xsl:attribute>
            <xsl:value-of select="$param-variable/@initial_value"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="Parameter">
            <xsl:attribute name="Name">
              <!-- get a unique parameter name for the parameter -->
              <xsl:variable name="unique-id">
                <xsl:call-template name="get-unique-parameter-name">
                  <xsl:with-param name="param-name" select="$parameter-name"/>
                </xsl:call-template>
              </xsl:variable>
              <!-- add it to the hashtable -->
              <xsl:variable name="dummy3" select="nameList:setMangledName(
                $mangledParamList,$parameter-name,'dummy',$unique-id)"/>
              <!-- and write it out -->
              <xsl:value-of select="$unique-id"/>
            </xsl:attribute>
            <xsl:text>0.0</xsl:text>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:if> <!-- check for already declared parameter -->
  </xsl:template> <!-- define-reaction-parameter -->
  
  <!--
  Named template: get-unique-parameter-name
  Used to ensure that when reaction parameters are used more than once
  they have unique identifers
  -->
  <xsl:template name="get-unique-parameter-name">
    <!-- the locally unique name -->
    <xsl:param name="param-name"/>
    
    <xsl:variable name="g-param-name" select="nameList:getMangledName(
      $gParamList,$param-name,'dummy')"/>
    <xsl:choose>
      <xsl:when test="string-length($g-param-name) > 0">
        <!-- the name has already been used, so append an '_' and
          try again -->
        <xsl:call-template name="get-unique-parameter-name">
          <xsl:with-param name="param-name" select="concat($param-name,'_')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <!-- we have a name which has not been used, so add it
          to the hashtable and write it out/return it -->
        <xsl:variable name="dummy" select="nameList:setMangledName(
          $gParamList,$param-name,'dummy',$param-name)"/>
        <xsl:value-of select="$param-name"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template> <!-- get-unique-parameter-name -->
  
  <!--
  Named template: mangle-parameter-names
  Takes an equation from a reaction and looks for parameter names
  that need to be mangled into their unique version for this specific
  reaction
  -->
  <xsl:template name="mangle-parameter-names">
    <!-- the expression to search through -->
    <xsl:param name="expression"/>
    <!-- the mapping of global parameters to their local names -->
    <xsl:param name="paramList"/>
    
    <xsl:variable name="mangled-expression" select="nameList:mangleString(
      $paramList,$expression)"/>
    <xsl:value-of select="$mangled-expression"/>
    
  </xsl:template> <!-- mangle-parameter-names -->
    
  <!-- A named template which will post-process a mathematical expression 
       string to handle the variable mapping -->
	<xsl:template name="post-process-math-expression">
		<!-- The string expression -->
		<xsl:param name="expression"/>
		<!-- The cellML component which contains the above expression -->
		<xsl:param name="component"/>
		<!--xsl:message>
    <xsl:text>
    
    Processing expression: </xsl:text>
    <xsl:value-of select="$component/@name"/><xsl:text>/</xsl:text><xsl:value-of select="$expression"/>
    <xsl:text>

</xsl:text>
    </xsl:message-->
		<xsl:if test="string-length($expression) > 0">
			<xsl:choose>
				<xsl:when test="substring($expression,1,1) = ' '">
					<xsl:text/>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = '('">
					<xsl:text>(</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = ')'">
					<xsl:text>)</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = '+'">
					<xsl:text>+</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = '-'">
					<xsl:text>-</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = '/'">
					<xsl:text>/</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = '*'">
					<xsl:text>*</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:when test="substring($expression,1,1) = ','">
					<xsl:text>,</xsl:text>
					<xsl:call-template name="post-process-math-expression">
						<xsl:with-param name="expression" select="substring($expression,2)"/>
						<xsl:with-param name="component" select="$component"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:choose>
						<xsl:when test="string-length(substring-before($expression,' '))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,' ')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text/>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,' ')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,'('))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,'(')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>(</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,'(')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,')'))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,')')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>)</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,')')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,'+'))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,'+')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>+</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,'+')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,'-'))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,'-')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>-</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,'-')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,'/'))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,'/')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>/</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,'/')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,'*'))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,'*')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>*</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,'*')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:when test="string-length(substring-before($expression,','))>0">
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="substring-before($expression,',')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
							<xsl:text>,</xsl:text>
							<xsl:call-template name="post-process-math-expression">
								<xsl:with-param name="expression" select="substring-after($expression,',')"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="process-variable-name">
								<xsl:with-param name="variable-name" select="$expression"/>
								<xsl:with-param name="component" select="$component"/>
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
		<!-- string-length($expression) > 0 -->
	</xsl:template>
	<!-- post-process-math-expression -->
	<!-- Named template to mangle the local variable names into their globally unique version -->
	<xsl:template name="process-variable-name">
		<!-- The unmangled variable name -->
		<xsl:param name="variable-name"/>
		<!-- The current component -->
		<xsl:param name="component"/>
		<!--xsl:message>
    <xsl:text>
    
    Processing variable: </xsl:text>
    <xsl:value-of select="$component/@name"/><xsl:text>/</xsl:text><xsl:value-of select="$variable-name"/>
    <xsl:text>

</xsl:text>
    </xsl:message-->
		<xsl:variable name="component-name" select="$component/@name"/>
		<xsl:choose>
			<xsl:when test="contains($variable-name,' ')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,'(')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,')')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,'+')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,'-')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,'*')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,'/')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="contains($variable-name,',')">
				<xsl:call-template name="post-process-math-expression">
					<xsl:with-param name="expression" select="$variable-name"/>
					<xsl:with-param name="component" select="$component"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<!-- first check if there is a variable declared in the current 
             component which matches the variable-name, if there isn't
             the variable-name is probably part of a VCML function
             and we can safely write it out as is -->
				<xsl:variable name="variable-element" select="$component/cellml:variable[@name = $variable-name]"/>
				<xsl:choose>
					<xsl:when test="$variable-element">
						<!-- The variable is a real cellML variable, so mangle its name accordingly -->
            <xsl:value-of select="nameManager:getMangledName($nameManager,$component-name,$variable-name)"/>
					</xsl:when>
					<xsl:otherwise>
						<!-- no variable found, so just write it out -->
						<xsl:value-of select="$variable-name"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template> <!-- process-variable-name -->

</xsl:stylesheet>
<!-- Stylus Studio meta-information - (c)1998-2002 eXcelon Corp.
<metaInformation>
<scenarios ><scenario default="yes" name="Scenario1" userelativepaths="yes" externalpreview="no" url="..\..\work\Les\MAPK_cascade_2001_corrected.xml" htmlbaseurl="" processortype="xalan" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/></scenarios><MapperInfo srcSchemaPath="" srcSchemaRoot="" srcSchemaPathIsRelative="yes" srcSchemaInterpretAsXML="no" destSchemaPath="" destSchemaRoot="" destSchemaPathIsRelative="yes" destSchemaInterpretAsXML="no"/>
</metaInformation>
-->