<?xml version="1.0" encoding="UTF-8"?>
<!-- The task of this stylesheet is to transform a framework description made in XML into applicaction XML schema. -->
<!-- by Vaclav Cechticky & Ondrej Rohlik (Automatic Control Laboratory, ETH Zuerich) -->
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fmm="http://www.pnp-software.com/XFeature/fmm"
  xmlns:fm="http://www.pnp-software.com/XFeature/fmm"
  xmlns:dm="http://www.pnp-software.com/XFeature/displayModel"
  xmlns:inst="http://www.pnp-software.com/XFeature/instantiation"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="xsi">
  <!-- To clarify: fm is needed for input xfm document and fmm is needed for output document -->
  <xsl:output method="xml"/>
  <!-- ========================================================================= -->
  <!-- The template matches any node. -->
  <xsl:template match="/">
    <xs:schema targetNamespace="http://www.pnp-software.com/XFeature/fmm"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:dm="http://www.pnp-software.com/XFeature/displayModel"
      xmlns:fmm="http://www.pnp-software.com/XFeature/fmm"
      xmlns:fm="http://www.pnp-software.com/XFeature/fmm"
      xmlns:inst="http://www.pnp-software.com/XFeature/instantiation" 
      elementFormDefault="qualified"
      attributeFormDefault="qualified" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://www.w3.org/2001/XMLSchema ../../general_files/MetaMetaModel.xfmmm">
      <xs:annotation>
        <xs:appinfo>
          <dm:OxygenToolXPathWorkaround/>
        </xs:appinfo>
      </xs:annotation>
      <xs:simpleType name="zero2inf">
        <xs:restriction base="xs:token">
          <xs:pattern value="([1-9][0-9]*|0|\+|\*)"/>
        </xs:restriction>
      </xs:simpleType>
      <xs:simpleType name="one2inf">
        <xs:restriction base="xs:token">
          <xs:pattern value="([1-9][0-9]*|\+|\*)"/>
        </xs:restriction>
      </xs:simpleType>
      <xs:simpleType name="greaterThanZero">
        <xs:restriction base="xs:token">
          <xs:pattern value="([1-9][0-9]*)"/>
        </xs:restriction>
      </xs:simpleType>
      <!-- Definition of simple elements -->
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="type" type="xs:string"/>
      <xs:attribute name="cardMin" type="fmm:zero2inf"/>
      <xs:attribute name="cardMax" type="fmm:one2inf"/>
      <xs:attribute name="value" type="xs:string"/>
      <xs:attribute name="text" type="xs:string"/>
      <xsl:apply-templates/>
      <!--  select="//fm:FeatureNode" -->
      <!-- TBDeleted -->
      <!-- <xsl:call-template name="CreateDescriptionElement"/> -->
      <!-- TBDeleted -->
      <!-- ============================ Property Sets ========================= -->
      <!-- COMPONENTS (if GENERABLE) -->
      <xsl:if test="//fm:ComponentPropertySet/fm:StatusProperty/@fm:value='generable'">
        <xs:element name="ComponentInstantiationPropertySet">
          <xs:complexType dm:displayType="propertySet">
            <xs:sequence>
              <xs:element ref="fmm:MissingClassNameProperty"/>
            </xs:sequence>
            <xs:attribute ref="fmm:value" use="required"/>
            <xs:anyAttribute namespace="##any" processContents="skip"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="MissingClassNameProperty">
          <xs:complexType dm:displayType="property">
            <xs:attribute name="value" type="xs:string" use="required"/>
          </xs:complexType>
        </xs:element>
      </xsl:if>
      <!-- ATTRIBUTES incl. Enumeration -->
      <xsl:for-each-group select="//fm:AttributePropertySet" group-by="fm:NameProperty/@fm:value">
        <xsl:variable name="featureName" select="fm:NameProperty/@fm:value"/>
        <xsl:variable name="featureType" select="fm:TypeProperty/@fm:value"/>
        <xs:element name="{$featureName}PropertySet">
          <xs:complexType dm:displayType="propertySet">
            <xs:sequence>
              <xs:element ref="fmm:{$featureName}Property"/>
            </xs:sequence>
            <xs:attribute ref="fmm:value" use="required"/>
            <xs:anyAttribute namespace="##any" processContents="skip"/>
          </xs:complexType>
        </xs:element>
        <xsl:choose>
          <xsl:when test="fm:TypeProperty/@fm:value">
            <xs:element name="{$featureName}Property">
              <xs:complexType dm:displayType="property">
                <xs:attribute name="value" type="{$featureType}" use="required"/>
              </xs:complexType>
            </xs:element>
          </xsl:when>
          <xsl:otherwise>
            <xs:simpleType name="{$featureName}Enumeration">
              <xs:restriction base="xs:string">
                <xsl:for-each select="fm:ValueItemProperty">
                  <xs:enumeration value="{@fm:value}"/>
                </xsl:for-each>
              </xs:restriction>
            </xs:simpleType>
            <xs:element name="{$featureName}Property">
              <xs:complexType dm:displayType="property">
                <xs:attribute name="value" type="fmm:{$featureName}Enumeration" use="required"/>
              </xs:complexType>
            </xs:element>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xs:schema>
  </xsl:template>
  <!-- end of template for the main xs:schema element -->
  <!-- ========================================================================= -->
  <!-- The template matches Feature element. -->
  <xsl:template match="/fm:FeatureModel">
    <xs:element name="FeatureModel">
      <xs:complexType dm:displayType="root">
        <xs:sequence>
          <xs:element ref="fmm:{/fm:FeatureModel/fm:FeatureNode/@fm:value}"/>
          <!-- Say, there will be no Annotation here (it is not obligatory, you know) -->
        </xs:sequence>
        <xs:attribute ref="fmm:value" use="required"/>
        <xs:anyAttribute namespace="##any" processContents="skip"/>
      </xs:complexType>
    </xs:element>
    <xsl:apply-templates/>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- The template matches Feature element. -->
  <xsl:template match="//fm:FeatureNode">
    <xsl:if test="not(fm:FeatureCardinality/@fm:cardMax='+' or fm:FeatureCardinality/@fm:cardMax='*' or fm:FeatureCardinality/@fm:cardMax='unbound')">
      <xsl:if test="fm:FeatureCardinality/@fm:cardMin gt fm:FeatureCardinality/@fm:cardMax">
        <xsl:message terminate="yes">ERROR: min cardinality (<xsl:value-of select="fm:FeatureCardinality/@fm:cardMin"/>) has to be less or equal to max cardinality (<xsl:value-of select="fm:FeatureCardinality/@fm:cardMax"/>).</xsl:message>
      </xsl:if>
    </xsl:if>   
    <xsl:call-template name="ProcessFeature"/>
    <xsl:apply-templates/>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- The template matches Group element -->
  <xsl:template match="//fm:GroupNode">
    <!-- create a new group -->
    <xs:group name="{@fm:value}">
      <!-- ========================================================================= -->
      <xsl:if test="not(fm:GroupCardinality/@fm:cardMax='+' or fm:GroupCardinality/@fm:cardMax='*' or fm:GroupCardinality/@fm:cardMax='unbound')">
        <xsl:if test="fm:GroupCardinality/@fm:cardMin gt fm:GroupCardinality/@fm:cardMax">
          <xsl:message terminate="yes">ERROR: min cardinality (<xsl:value-of select="fm:GroupCardinality/@fm:cardMin"/>) has to be less or equal to max cardinality (<xsl:value-of select="fm:GroupCardinality/@fm:cardMax"/>).</xsl:message>
        </xsl:if>
        <xsl:if test="(count(child::fm:FeatureNode) + count(child::fm:CallMacroNode)) &lt; fm:GroupCardinality/@fm:cardMax">
          <xsl:message terminate="yes">ERROR: there are less child elements (<xsl:value-of select="count(child::fm:FeatureNode) + count(child::fm:CallMacroNode)"/>) of group '<xsl:value-of select="@fm:value"/>' than is the max cardinality (<xsl:value-of select="fm:GroupCardinality/@fm:cardMax"/>) of the group.</xsl:message>
        </xsl:if>
      </xsl:if>   
      <!-- It processes a group cardinality in case that the minimal cardinality is 1 and maximal 1 -->
      <xsl:if test="(fm:GroupCardinality/@fm:cardMin=1) and (fm:GroupCardinality/@fm:cardMax=1)">
        <xsl:if test="count(child::fm:FeatureNode | child::fm:CallMacroNode)=1">
          <xsl:if test="(count(child::fm:FeatureNode)=1) and (count(child::fm:CallMacroNode)=0)">
            <xs:sequence>
              <xsl:for-each select="fm:FeatureNode">
                <xsl:call-template name="RefFeature"/>
              </xsl:for-each>
            </xs:sequence>
          </xsl:if>
          <xsl:if test="(count(child::fm:FeatureNode)=0) and (count(child::fm:CallMacroNode)=1)">
            <xs:sequence>
              <xsl:for-each select="fm:CallMacroNode">
                <xsl:call-template name="RefCallMacro"/>
              </xsl:for-each>
            </xs:sequence>
          </xsl:if>
        </xsl:if>
        <xsl:if test="count(child::fm:FeatureNode | child::fm:CallMacroNode)&gt;1">
          <xs:choice>
            <xsl:for-each select="fm:FeatureNode">
              <xsl:call-template name="RefFeature"/>
            </xsl:for-each>
            <xsl:for-each select="fm:CallMacroNode">
              <xsl:call-template name="RefCallMacro"/>
            </xsl:for-each>
          </xs:choice>
        </xsl:if>
      </xsl:if>
      <!-- ========================================================================= -->
      <!-- It processes a group cardinality in case that the minimal cardinality is 1 and maximal bigger than 1 -->
      <xsl:if test="(fm:GroupCardinality/@fm:cardMin&gt;=1) and (fm:GroupCardinality/@fm:cardMax&gt;1)">
        <xs:choice>
          <xsl:call-template name="ExpandGroupCardinality">
            <xsl:with-param name="minCard" select="fm:GroupCardinality/@fm:cardMin"/>
            <xsl:with-param name="maxCard" select="fm:GroupCardinality/@fm:cardMax"/>
          </xsl:call-template>
        </xs:choice>
      </xsl:if>
      <!-- ========================================================================= -->
      <!-- It processes a group cardinality in case that the minimal cardinality is 0 and maximal equal or bigger than 1 -->
      <xsl:if test="(fm:GroupCardinality/@fm:cardMin=0) and (fm:GroupCardinality/@fm:cardMax&gt;=1)">
        <xs:choice>
          <xsl:call-template name="ExpandGroupCardinality">
            <xsl:with-param name="minCard" select="1"/>
            <xsl:with-param name="maxCard" select="fm:GroupCardinality/@fm:cardMax"/>
          </xsl:call-template>
        </xs:choice>
      </xsl:if>
    </xs:group>
    <xsl:apply-templates/>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- The template makes all possible combinations of features defined in a group based on group cardinality. -->
  <xsl:template name="ExpandGroupCardinality">
    <!-- store minimal group cardinality -->
    <xsl:param name="minCard"/>
    <!-- store maximal group cardinality -->
    <xsl:param name="maxCard"/>
    <xsl:variable name="minCombinationLength" select="$minCard"/>
    <xsl:variable name="maxCombinationLength" select="$maxCard"/>
    <!-- the current length of the combination -->
    <xsl:variable name="currentLength" select="1"/>
    <!-- The loop makes combinations for each feature or callmacro that is direct child of the group element,
		the length of combinations is driven by minimal and maximal combination length. -->
    <xsl:for-each select="fm:FeatureNode | fm:CallMacroNode">
      <xsl:if test="count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=($minCombinationLength+(-1))">
        <xs:sequence>
          <xsl:if test="self::fm:FeatureNode">
            <xsl:call-template name="RefFeature"/>
          </xsl:if>
          <xsl:if test="self::fm:CallMacroNode">
            <xsl:call-template name="RefCallMacro"/>
          </xsl:if>
          <xsl:if test="count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=1">
            <!-- it calls template where the combination are made by recursion -->
            <xsl:call-template name="MakeCombinations">
              <xsl:with-param name="list" select="following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode"/>
              <xsl:with-param name="minCombinationLength" select="$minCombinationLength"/>
              <xsl:with-param name="maxCombinationLength" select="$maxCombinationLength"/>
              <xsl:with-param name="currentLength" select="$currentLength+1"/>
            </xsl:call-template>
          </xsl:if>
        </xs:sequence>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- The template MakeCombinations is called from ExpandGroupCardinality template. MakeCombination makes the combination by recursion. -->
  <xsl:template name="MakeCombinations">
    <xsl:param name="list"/>
    <xsl:param name="minCombinationLength"/>
    <xsl:param name="maxCombinationLength"/>
    <xsl:param name="currentLength"/>
    <xsl:if test="($minCombinationLength&gt;=$currentLength) and ($maxCombinationLength&gt;$currentLength) and count($list)&gt;=1">
      <xs:choice>
        <xsl:for-each select="$list">
          <xsl:if test="(count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=($maxCombinationLength+(-$currentLength))) or (count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=($minCombinationLength+(-$currentLength)))">
            <xs:sequence>
              <xsl:if test="self::fm:FeatureNode">
                <xsl:call-template name="RefFeature"/>
              </xsl:if>
              <xsl:if test="self::fm:CallMacroNode">
                <xsl:call-template name="RefCallMacro"/>
              </xsl:if>
              <xsl:call-template name="MakeCombinations">
                <xsl:with-param name="list" select="following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode"/>
                <xsl:with-param name="minCombinationLength" select="$minCombinationLength"/>
                <xsl:with-param name="maxCombinationLength" select="$maxCombinationLength"/>
                <xsl:with-param name="currentLength" select="$currentLength+1"/>
              </xsl:call-template>
            </xs:sequence>
          </xsl:if>
        </xsl:for-each>
      </xs:choice>
    </xsl:if>
    <xsl:if test="($minCombinationLength&lt;$currentLength) and ($maxCombinationLength&gt;$currentLength) and count($list)&gt;=1">
      <xs:choice minOccurs="0">
        <xsl:for-each select="$list">
          <xsl:if test="(count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=($maxCombinationLength+(-$currentLength))) or (count(following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode)&gt;=($minCombinationLength+(-$currentLength)))">
            <xs:sequence>
              <xsl:if test="self::fm:FeatureNode">
                <xsl:call-template name="RefFeature"/>
              </xsl:if>
              <xsl:if test="self::fm:CallMacroNode">
                <xsl:call-template name="RefCallMacro"/>
              </xsl:if>
              <xsl:call-template name="MakeCombinations">
                <xsl:with-param name="list" select="following-sibling::fm:FeatureNode | following-sibling::fm:CallMacroNode"/>
                <xsl:with-param name="minCombinationLength" select="$minCombinationLength"/>
                <xsl:with-param name="maxCombinationLength" select="$maxCombinationLength"/>
                <xsl:with-param name="currentLength" select="$currentLength+1"/>
              </xsl:call-template>
            </xs:sequence>
          </xsl:if>
        </xsl:for-each>
      </xs:choice>
    </xsl:if>
    <xsl:if test="($currentLength=$maxCombinationLength) and ($minCombinationLength=$maxCombinationLength) and count($list)&gt;=1">
      <xs:choice>
        <xsl:for-each select="$list">
          <xsl:if test="self::fm:FeatureNode">
            <xsl:call-template name="RefFeature"/>
          </xsl:if>
          <xsl:if test="self::fm:CallMacroNode">
            <xsl:call-template name="RefCallMacro"/>
          </xsl:if>
        </xsl:for-each>
      </xs:choice>
    </xsl:if>
    <xsl:if test="($currentLength=$maxCombinationLength) and ($minCombinationLength&lt;$maxCombinationLength) and count($list)&gt;=1">
      <xs:choice minOccurs="0">
        <xsl:for-each select="$list">
          <xsl:if test="self::fm:FeatureNode">
            <xsl:call-template name="RefFeature"/>
          </xsl:if>
          <xsl:if test="self::fm:CallMacroNode">
            <xsl:call-template name="RefCallMacro"/>
          </xsl:if>
        </xsl:for-each>
      </xs:choice>
    </xsl:if>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- ProcessFeature template processes the tag 'Feature'. -->
  <xsl:template name="ProcessFeature">
    <xs:element name="{@fm:value}">
      <!-- process feature properties, description, group and type -->
      <!-- XXX O.R. next line ommitted for XFeature XXX -->
      <!-- <xsl:call-template name="Description"/> -->
      <xs:complexType dm:displayType="node">
        <xsl:call-template name="Annotation"/>
        <xs:sequence>
          <!-- it makes a  reference to globally defined 'Description' element -->
          <!-- XXX O.R. next line ommitted for XFeature XXX -->
          <!-- <xs:element ref="Description" minOccurs="0"/> -->
          <xsl:for-each select="fm:GroupNode">
            <xsl:choose>
              <xsl:when test="(fm:GroupCardinality/@fm:cardMin=0) and (fm:GroupCardinality/@fm:cardMax&gt;=1)">
                <xs:group ref="fmm:{@fm:value}" minOccurs="0"/>
              </xsl:when>
              <xsl:otherwise>
                <!-- it makes a  reference to globally defined group element -->
                <xs:group ref="fmm:{@fm:value}"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
          <xsl:call-template name="PropertySet"/>
        </xs:sequence>
        <!-- This calls 'Type' template that is further processing different subtypes. -->
        <!-- XXX to be changed to choice of propertySet -->
        <!-- <xsl:call-template name="PropertySet"/> -->
        <xs:attribute ref="fmm:value" use="required"/>
        <xs:anyAttribute namespace="##any" processContents="skip"/>
      </xs:complexType>
    </xs:element>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- RefFeature template processes the tag 'Feature'. -->
  <xsl:template name="RefFeature">
    <xsl:choose>
      <xsl:when test="(fm:FeatureCardinality/@fm:cardMax='+') or (fm:FeatureCardinality/@fm:cardMax='*')">
        <xs:element ref="fmm:{@fm:value}">
          <xsl:attribute name="minOccurs">
            <xsl:value-of select="fm:FeatureCardinality/@fm:cardMin"/>
          </xsl:attribute>
          <xsl:attribute name="maxOccurs">
            <xsl:value-of select="'unbounded'"/>
          </xsl:attribute>
        </xs:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:if test="(fm:FeatureCardinality/@fm:cardMax&gt;=1)">
          <xs:element ref="fmm:{@fm:value}">
            <xsl:attribute name="minOccurs">
              <xsl:value-of select="fm:FeatureCardinality/@fm:cardMin"/>
            </xsl:attribute>
            <xsl:attribute name="maxOccurs">
              <xsl:value-of select="fm:FeatureCardinality/@fm:cardMax"/>
            </xsl:attribute>
          </xs:element>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- RefFeatureMinZero template processes the tag 'Feature'. -->
  <xsl:template name="RefFeatureMinOccursZero">
    <xsl:if test="(fm:FeatureCardinality/@fm:cardMax&gt;=1)">
      <xs:element ref="fmm:{@fm:value}">
        <xsl:attribute name="minOccurs">
          <xsl:value-of select="0"/>
        </xsl:attribute>
        <xsl:attribute name="maxOccurs">
          <xsl:value-of select="fm:FeatureCardinality/@fm:cardMax"/>
        </xsl:attribute>
      </xs:element>
    </xsl:if>
    <xsl:if test="(fm:FeatureCardinality/@fm:cardMax='+') or (fm:FeatureCardinality/@fm:cardMax='*')">
      <xs:element ref="fmm:{@fm:value}">
        <xsl:attribute name="minOccurs">
          <xsl:value-of select="0"/>
        </xsl:attribute>
        <xsl:attribute name="maxOccurs">
          <xsl:value-of select="'unbounded'"/>
        </xsl:attribute>
      </xs:element>
    </xsl:if>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- RefCallMacro template processes the tag 'CallMacro'. -->
  <xsl:template name="RefCallMacro">
    <xsl:variable name="mName" select="@fm:value"/>
    <!-- XXX O.R. Marco_Name ma dve zvlastnosti: 1) ma podrzitko a 2) nema namespace -->
    <xsl:choose>
      <xsl:when test="//fm:MacroFeatureNode[@fm:value=$mName]">
        <xsl:for-each select="//fm:MacroFeatureNode[@fm:value=$mName]">
          <xsl:for-each select="fm:FeatureNode">
            <xsl:call-template name="RefFeature"/>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message terminate="yes">ERROR: Called macro <xsl:value-of select="$mName"/> does NOT exist.</xsl:message>
      </xsl:otherwise>
    </xsl:choose>
    
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- RefCallMacroMinOccursZero template processes the tag 'CallMacro'. -->
  <xsl:template name="RefCallMacroMinOccursZero">
    <xsl:variable name="mName" select="fm:MacroNameProperty/@fm:value"/>
    <!-- XXX O.R. Marco_Name ma dve zvlastnosti: 1) ma podrzitko a 2) nema namespace -->
    <xsl:for-each select="//fm:MacroFeatureNode[@fm:value=$mName]">
      <xsl:for-each select="fm:FeatureNode">
        <xsl:call-template name="RefFeatureMinOccursZero"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="PropertySet">
    <!-- It is now called separately
        <xsl:if test="fm:Annotation">
            <xsl:call-template name="Annotation"/>
        </xsl:if> -->
    <xsl:if test="fm:CompositePropertySet">
      <xsl:call-template name="CompositePropertySet"/>
    </xsl:if>
    <xsl:if test="fm:ComponentPropertySet">
      <xsl:call-template name="ComponentPropertySet"/>
    </xsl:if>
    <xsl:if test="fm:AbstractInterfacePropertySet">
      <xsl:call-template name="AbstractInterfacePropertySet"/>
    </xsl:if>
    <xsl:if test="fm:AspectPropertySet">
      <xsl:call-template name="AspectPropertySet"/>
    </xsl:if>
    <xsl:if test="fm:AttributePropertySet">
      <xsl:call-template name="AttributePropertySet"/>
    </xsl:if>
    <xsl:if test="fm:OperationPropertySet">
      <xsl:call-template name="OperationPropertySet"/>
    </xsl:if>
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="OperationPropertySet">
    <!-- No additional information needed - everything is in family model -->
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="AspectPropertySet">
    <!-- No additional information needed - everything is in family model (maybe it can be provided/generable/missing but this is not in ICSR.xfmm) -->
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="AbstractInterfacePropertySet">
    <!-- No additional information needed - everything is in family model -->
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="ComponentPropertySet">
    <!-- <inst:InstantiatioInstructions type="foo" status="bar"/> -->
    <xsl:if test="fm:ComponentPropertySet/fm:StatusProperty/@fm:value='generable'">
      <xs:element ref="fmm:ComponentInstantiationPropertySet"/>
    </xsl:if>
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="AttributePropertySet">
    <xsl:if test="fm:AttributePropertySet/fm:NameProperty/@fm:value">
      <xs:element ref="fmm:{fm:AttributePropertySet/fm:NameProperty/@fm:value}PropertySet"/>
    </xsl:if>
  </xsl:template>
  <!-- ========================================================================= -->
  <xsl:template name="CompositePropertySet">
    <!-- No additional information needed - everything is in family model -->
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- Description template extracts information from feature types and write them into 'annotation' element. -->
  <xsl:template name="Annotation">
    <!-- was Description -->
    <xs:annotation>
      <xs:documentation>
        <xsl:value-of select="fm:Annotation/fm:ShortDescription/@fm:value"/>
        <xsl:if test="fm:Annotation/fm:LongDescription">
          <xsl:text> </xsl:text>
          <xsl:value-of select="fm:Annotation/fm:LongDescription/@fm:value"/>
        </xsl:if> 
        <xsl:if test="fm:Annotation/fm:LongDescription | fm:Annotation/fm:ShortDescription">
          <xsl:text> </xsl:text>
        </xsl:if>  
        <xsl:if test="fm:CompositePropertySet">The feature is of type composite.</xsl:if>
        <xsl:if test="fm:ComponentPropertySet">The feature is of type component. It is represented
          by '<xsl:value-of select="fm:ComponentPropertySet/fm:StatusProperty/@fm:value"/>'
          component '<xsl:value-of select="fm:ComponentPropertySet/fm:TypeProperty/@fm:value"/>'.</xsl:if>
        <xsl:if test="fm:AbstractInterfacePropertySet">The feature is of type abstract interface.</xsl:if>
        <xsl:if test="fm:AspectPropertySet">The feature is of type aspect.</xsl:if>
        <xsl:if test="fm:AttributePropertySet">The feature is of type attribute.</xsl:if>
        <xsl:if test="fm:OperationPropertySet">The feature is of type operation.</xsl:if>
        
      </xs:documentation>
    </xs:annotation>
  </xsl:template>
  <!-- ========================================================================= -->
  <!-- The template creates a global element called 'Description' where the developer of an application can write any commnets.  -->
  <xsl:template name="CreateDescriptionElement">
    <xs:element name="Description">
      <xs:complexType mixed="true">
        <xs:sequence>
          <xs:any minOccurs="0" processContents="lax"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xsl:template>
</xsl:stylesheet>

